Como lo entiendo, el origen de su problema es que la plantilla de expresiones temporales puede tener referencias/punteros a algunos otros temporales. Y mediante el uso de auto & & solo ampliamos la vida útil de la plantilla de expresión en sí misma, pero no la duración de las temporarias a las que tiene referencias. ¿Es correcto?
Por ejemplo, ¿es this su caso?
#include <iostream>
#include <deque>
#include <algorithm>
#include <utility>
#include <memory>
using namespace std;
deque<bool> pool;
class ExpressionTemp;
class Scalar
{
bool *alive;
friend class ExpressionTemp;
Scalar(const Scalar&);
Scalar &operator=(const Scalar&);
Scalar &operator=(Scalar&&);
public:
Scalar()
{
pool.push_back(true);
alive=&pool.back();
}
Scalar(Scalar &&rhs)
: alive(0)
{
swap(alive,rhs.alive);
}
~Scalar()
{
if(alive)
(*alive)=false;
}
};
class ExpressionTemp
{
bool *operand_alive;
public:
ExpressionTemp(const Scalar &s)
: operand_alive(s.alive)
{
}
void do_job()
{
if(*operand_alive)
cout << "captured operand is alive" << endl;
else
cout << "captured operand is DEAD!" << endl;
}
};
ExpressionTemp expression(const Scalar &s)
{
return {s};
}
int main()
{
{
expression(Scalar()).do_job(); // OK
}
{
Scalar lv;
auto &&rvref=expression(lv);
rvref.do_job(); // OK, lv is still alive
}
{
auto &&rvref=expression(Scalar());
rvref.do_job(); // referencing to dead temporary
}
return 0;
}
Si sí, entonces una de las posibles soluciones, es hacer tipo especial de provisionales plantilla de expresión que poseen recursos movido de los temporales.
Por ejemplo, consulte el enfoque this (puede definir la macro BUG_CASE, para obtener de nuevo el caso de error).
//#define BUG_CASE
#include <iostream>
#include <deque>
#include <algorithm>
#include <utility>
#include <memory>
using namespace std;
deque<bool> pool;
class ExpressionTemp;
class Scalar
{
bool *alive;
friend class ExpressionTemp;
Scalar(const Scalar&);
Scalar &operator=(const Scalar&);
Scalar &operator=(Scalar&&);
public:
Scalar()
{
pool.push_back(true);
alive=&pool.back();
}
Scalar(Scalar &&rhs)
: alive(0)
{
swap(alive,rhs.alive);
}
~Scalar()
{
if(alive)
(*alive)=false;
}
};
class ExpressionTemp
{
#ifndef BUG_CASE
unique_ptr<Scalar> resource; // can be in separate type
#endif
bool *operand_alive;
public:
ExpressionTemp(const Scalar &s)
: operand_alive(s.alive)
{
}
#ifndef BUG_CASE
ExpressionTemp(Scalar &&s)
: resource(new Scalar(move(s))), operand_alive(resource->alive)
{
}
#endif
void do_job()
{
if(*operand_alive)
cout << "captured operand is alive" << endl;
else
cout << "captured operand is DEAD!" << endl;
}
};
template<typename T>
ExpressionTemp expression(T &&s)
{
return {forward<T>(s)};
}
int main()
{
{
expression(Scalar()).do_job(); // OK, Scalar is moved to temporary
}
{
Scalar lv;
auto &&rvref=expression(lv);
rvref.do_job(); // OK, lv is still alive
}
{
auto &&rvref=expression(Scalar());
rvref.do_job(); // OK, Scalar is moved into rvref
}
return 0;
}
Sus sobrecargas operador/función puede devolver different types, en función de T & &/const T & argumentos:
#include <iostream>
#include <ostream>
using namespace std;
int test(int&&)
{
return 1;
}
double test(const int&)
{
return 2.5;
};
int main()
{
int t;
cout << test(t) << endl;
cout << test(0) << endl;
return 0;
}
lo tanto, cuando la plantilla de la expresión temporal no tienen recursos movido de los temporales - es el tamaño no se verá afectado.
Si prohibió tal encuadernación, 'operator + (expression_template const &, expression_template const &)' no compilaría tampoco. –
@ R.MartinhoFernandes: ¿Por qué 'operator +' toma sus argumentos por 'expression_template const &'? Podría imaginarme que 'operator +' podría tomar sus argumentos a través de algún tipo de proxy que todavía no permitiría que 'const reference's se vincule inseguramente con las plantillas de expresiones. (No digo que sea posible, pero al menos no es trivialmente imposible). – Mankarse
@Mankarse No puede mezclar las conversiones implícitas y la deducción del tipo de plantilla. Como tiene que elegir la deducción de tipo para 'operator +' para trabajar, los argumentos deben ser del tipo de la plantilla de expresión. (A menos que no entienda lo que quiere decir con "algún tipo de proxy") –