我正在开发一个简单的包装模板类,该类在调用特殊成员函数时进行记录。这些函数不能默认,因为它们执行额外的日志相关任务。
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_;
};
不幸的是,当包装类型是右值引用时,复制构造函数无法编译并显示以下错误消息:
错误:无法将“int”左值绑定到“int&&”</p>
原因是隐式复制构造函数对于右值引用成员的行为会有所不同:
[class.copy 12.8/15] 非联合类的隐式定义的复制/移动构造函数
X
执行其基类和成员的成员复制/移动。[...]或者x
是构造函数的参数,或者对于移动构造函数,是一个引用参数的 xvalue。每个基本或非静态数据成员都以适合其类型的方式复制/移动:
- 如果成员是一个数组,则每个元素都直接使用 ; 的相应子对象进行初始化
x
。- 如果成员 m 具有右值引用类型
T&&
,则使用static_cast<T&&>(x.m)
;直接初始化它。- 否则,基数或成员将直接用 的相应基数或成员初始化
x
。
这让我想到了我的问题:即使在使用rvalue-references作为成员时,如何编写一个表现为隐式定义的copy-constructor的通用复制构造函数。
对于这种特殊情况,我可以为rvalue-references添加一个额外的特化。但是,我正在寻找一种不限于单个成员并且不引入代码重复的通用解决方案。