【发布时间】:2013-09-26 23:46:30
【问题描述】:
我正在开发一个简单的包装模板类,它会在调用特殊成员函数时进行记录。这些函数不能默认,因为它们执行额外的日志相关任务。
template <typename T>
struct logger {
logger(T const& value) : value_(value) { /*...log...*/ }
logger(T&& value) : value_(std::move(value)) { /*...log...*/ }
logger(logger const& other) : value_(other.value_) { /*...log...*/ }
logger(logger&& other) : value_(std::move(other.value_)) { /*...log...*/ }
T value_;
};
不幸的是,当包装类型是 rvalue-reference 时,copy-constructor 无法编译并显示以下错误消息:
错误:无法将‘int’左值绑定到‘int&&’
原因是隐式复制构造函数对于 rvalue-reference 成员的行为会有所不同:
[class.copy 12.8/15] 非联合类
X的隐式定义的复制/移动构造函数执行其基类和成员的成员复制/移动。 [...] 让x成为构造函数的参数,或者对于移动构造函数来说,是一个引用参数的xvalue。每个基本或非静态数据成员都以适合其类型的方式复制/移动:
- 如果成员是数组,每个元素直接用
x的对应子对象初始化;- 如果成员m有右值引用类型
T&&,则直接用static_cast<T&&>(x.m)初始化;- 否则,基址或成员将直接使用
x的相应基址或成员进行初始化。
这让我想到了我的问题:如何编写一个通用的 copy-constructor,即使使用 rvalue-references 作为成员。
对于这种特殊情况,我可以为 rvalue-references 添加一个额外的特化。但是,我正在寻找一种不限于单个成员并且不会引入代码重复的通用解决方案。
【问题讨论】:
-
你不能不做
logger(logger const& other) : value_(static_cast<T>(other.value_))吗?因为T是int&& -
Kal:
T是int&&仅在一种特殊情况下,在另一种情况下它可能是一个巨大的对象,这会创建一个不必要的副本。 -
如果
T是右值引用,你想做什么?在这种情况下,您没有值语义。在这种情况下,也应该禁用移动 ctor,以避免生命周期问题。 -
@DyP:我想做与隐式复制构造函数相同的操作。也就是说,传播引用。
-
对于右值引用数据成员,默认隐式复制ctor被删除。
标签: c++ c++11 rvalue-reference