我对c ++隐式复制构造函数的理解类似于
T(T const& x) :
base1(x), base2(x) ... ,
var1(x.var1), var2(x.var2)...
{}
移动构造函数,复制&移动任务也遵循类似的模式。
为什么没有定义类似于以下内容?
T(T const& x) :
base1(static_cast<base1 const&>(x)),
base2(static_cast<base2 const&>(x)) ... ,
var1(x.var1), var2(x.var2)...
{}
示例
我有一个具有隐式复制/移动构造函数/赋值运算符的类,以及一些转换构造函数。我把这份工作委托给了一些实施课。
class common_work //common implementation of many work like classes
{
common_work(common_work const&) = default;
common_work(common_work&&) = default;// ... implicit constructors work for me.
//a forwarding constructor which can take many work like objects
template<class T, enable_if<work_like<T> > >
common_work(T&& x) { ... }
};
class work1 //one of the implementation
{
work1(work1 const& ) = default;
work1(work1&& ) = default; ...
common_work impl_;
};
这很好,因为work1
复制/移动构造函数正在为common_work
调用复制/移动构造函数,并且转发构造函数被其他构造函数[未在代码中显示]使用,这些构造函数从另一种构造函数转换而来work
。
然后我想从EBO和其他原因继承work1
common_work
。所以新的work1
类看起来像
class work1 : private common_work
{
work1(work1 const& ) = default;
work1(work1&& ) = default; ...
};
但是,因为work1
是一个work_like
类,所以转发构造函数突然得到了更好的匹配,因为common_work
的复制/移动构造函数需要static_cast
派生到基地。
注意:
common_work
作为CRTP,即作为模板参数传递的派生类类型,并在转发构造函数中将其过滤为enable_if<and_<work_like<T>,not_<is_same<T,Derived> > > >
。否则,我必须手动将work1
和static_cast
的复制/移动构造函数/赋值明确地写入基类,这样会出错,容易出错并且存在维护危险。答案 0 :(得分:1)
几年前在MSVC ++ bugstracker页面上讨论过这个问题(所以如果它还没有修复,那么它就是MSVC ++上的一个已知问题)。标准说
- ...使用x的相应基数或成员对基数或成员进行直接初始化。
当我阅读bug报告时,我确实测试了各种编译器,并且所有这些编译器都“神奇地投入”。标准似乎在细节上很安静(也有关于价值类别和c / v限定符),并且只是说“带有相应的基数...... x”,如果你认为它意味着IMO更有意义“不是x,而是使用x的相应基数......”而不是将它传递给完整的对象(我甚至会说它只能 这样理解) 。