模板“复制构造函数”不会阻止编译器生成的移动构造函数

时间:2014-07-18 19:10:55

标签: c++ c++11

考虑以下计划及其中的评论:

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定义来获得我需要的所有东西吗?如果是的话,我可以避免明确地“默认”它们。

3 个答案:

答案 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;,并且没有其他参数,或者其余的参数都有默认值。