据我理解,你的问题根源在于表达式模板临时变量可能会引用/指向其他临时变量。而使用auto&&只会延长表达式模板临时变量本身的生命周期,而不是它所引用的临时变量的生命周期。这样说对吗?
例如,
this是你的情况吗?
#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();
}
{
Scalar lv;
auto &&rvref=expression(lv);
rvref.do_job();
}
{
auto &&rvref=expression(Scalar());
rvref.do_job();
}
return 0;
}
如果是这样,可能的解决方案之一是创建一种特殊的表达式模板临时变量来保存从临时变量移动的资源。
例如,请查看
此 方法(您可以定义 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;
#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();
}
{
Scalar lv;
auto &&rvref=expression(lv);
rvref.do_job();
}
{
auto &&rvref=expression(Scalar());
rvref.do_job();
}
return 0;
}
您的操作符/函数重载可以根据T&&/const T&参数返回
不同类型:
#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;
}
因此,当您的表达式模板暂时没有从临时变量中移动的资源时,其大小将不受影响。
operator+(expression_template const&, expression_template const&)
也将无法编译。 - R. Martinho Fernandesexpression_template const&
来传递operator+
的参数?我可以想象operator+
可以通过某种代理来接受其参数,该代理仍将禁止将const reference
不安全地绑定到表达式模板上。(我并不是说这是可能的,但至少不是显然不可能的)。 - Mankarse