Như tôi chưa hiểu, gốc của vấn đề của bạn là mẫu biểu thức tạm thời có thể có tham chiếu/con trỏ đến một số thời gian khác. Và bằng cách sử dụng tự động & &, chúng tôi chỉ mở rộng vòng đời của biểu mẫu tạm thời, nhưng không phải là thời gian tồn tại của thời gian mà nó có tham chiếu đến. Có đúng không?
Ví dụ: this trường hợp của bạn?
#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;
}
Nếu có thì một trong các giải pháp có thể là tạo các loại biểu mẫu đặc biệt tạm thời giữ tài nguyên được chuyển từ trạng thái tạm thời.
Ví dụ: hãy kiểm tra phương pháp this (bạn có thể xác định macro BUG_CASE, để nhận lại trường hợp lỗi).
//#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;
}
của bạn quá tải toán tử/chức năng có thể trở lại different types, tùy thuộc vào T & &/const T & đối số:
#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;
}
Vì vậy, khi bạn mẫu biểu tạm thời không có nguồn lực chuyển từ temporaries - đó là kích thước sẽ không bị ảnh hưởng.
Nguồn
2012-10-21 14:14:30
Nếu bạn cấm ràng buộc như vậy, 'toán tử + (expression_template const &, expression_template const &)' cũng sẽ không biên dịch. –
@ R.MartinhoFernandes: Tại sao 'toán tử +' lấy các đối số của nó bằng 'expression_template const &'? Tôi có thể tưởng tượng rằng 'toán tử +' có thể lấy các đối số của nó thông qua một số loại proxy mà sẽ vẫn không cho phép 'tham chiếu const' bị ràng buộc không chắc chắn với các mẫu biểu thức. (Tôi không nói điều đó là có thể, nhưng ít nhất cũng không phải là không thể). – Mankarse
@Mankarse Bạn không thể kết hợp chuyển đổi ngầm định và khấu trừ loại mẫu. Vì bạn phải chọn loại khấu trừ cho 'toán tử +' để làm việc, các đối số cho nó phải là kiểu của mẫu biểu thức. (Trừ khi tôi hiểu lầm ý bạn là "một số loại proxy") –