考虑以下计划及其中的评论:
template<class T>
struct S_ {
S_() = default;
// The template version does not forbid the compiler
// to generate the move constructor implicitly
template<class U> S_(const S_<U>&) = delete;
// If I make the "real" copy constructor
// user-defined (by deleting it), then the move
// constructor is NOT implicitly generated
// S_(const S_&) = delete;
};
using S = S_<int>;
int main() {
S s;
S x{static_cast<S&&>(s)};
}
问题是:为什么用户定义模板构造函数(当U = T时它有效地充当复制构造函数)阻止编译器生成移动构造函数,而相反,如果我用户定义“真正的”复制构造函数(通过删除它),那么移动构造函数不会隐式生成(程序不会编译)? (可能原因是“模板版本”在T = U时也不尊重复制构造函数的标准定义。)。
好处是,这似乎显然是我想要的。事实上,我需要所有副本并移动构造函数和 所有编译器将隐式生成的移动和复制赋值运算符,就好像S是简单地定义为template<class U> S{};
加上来自其他S<U>
的转化的模板构造函数。按照标准,我可以依靠上面的S定义来获得我需要的所有东西吗?如果是的话,我可以避免明确地“默认”它们。
答案 0 :(得分:5)
答案很简单 - 没有(!)模板复制构造函数。即使模板参数与复制构造函数的参数匹配,也不是复制构造函数。
请参见12.8复制和移动类对象
类X的非模板构造函数是复制构造函数(如果是) 第一个参数是X&amp;类型,const X&amp;,volatile X&amp;或const volatile X&amp;,并且没有其他参数或其他所有参数 参数有默认参数(8.3.6)。 [例子:X :: X(const X&amp;) 和X :: X(X&amp;,int = 1)是复制构造函数。
类似适用于移动构造函数
答案 1 :(得分:4)
没有模板化复制构造函数。仍然生成常规(非模板化)复制构造函数,并且比使用您提供的签名的模板化复制构造函数更好地匹配(事情变得更加复杂,混合中引入了#34;通用&#34;引用,但是关闭 - 主题)。
答案 2 :(得分:2)
复制构造函数和移动构造函数不是模板化的。 C ++标准特定于复制构造函数的构成。
来自:http://en.cppreference.com/w/cpp/language/copy_constructor
T类的复制构造函数是非模板构造函数,其第一个参数是T&amp;,const T&amp;,volatile T&amp;或const volatile T&amp;,并且没有其他参数,或者其余的参数都有默认值。