当有模板副本ctor

时间:2017-07-06 13:17:28

标签: c++ c++11 c++14

template<class T>
class MyClass {
 public:
  //MyClass() = default;

 template<class X>
 MyClass(MyClass<X>& other)
 {
  val = other.getVal();
 }

 T getVal()
 {
  return val;
 }

 private:
  T val;
};

main()
{
 MyClass<double> xd;       //this one causing the problem
 MyClass<double> xd1(xd);  //this one is fine

 MyClass<int> xi(xd);
}

此代码无法编译。 但如果你取消注释MyClass()= default,那么一切都很好。 据我所知,模板不会阻止编译器生成默认的ctor和复制ctor 。 实际上编译器只在尝试通过默认ctor创建对象时抱怨,而不是在复制构造(在这种情况下是编译器生成) 代码是用g ++ 5.4.0和7.1.0编译的。与

相同的行为

1 个答案:

答案 0 :(得分:7)

这不是复制构造函数:

template<class X>
MyClass(MyClass<X>& other) {
    val = other.getVal();
}

这是一个构造函数,它将可变左值引用引用到许多不同于此类的类型。

这是一个复制构造函数:

MyClass(const MyClass&) {
    // ...
}

您可以通过尝试将= default放在其签名之后来测试函数是否为特殊函数。如果编译器抱怨你滥用默认函数,那么你的功能并不是特别的。

当添加除特殊构造函数之外的任何其他构造函数时,不会生成默认构造函数。该函数作为模板与非模板函数没有任何不同的效果。在这种情况下,确实需要MyClass() = default

来自cppreference:

  

如果没有为类类型(struct,class或union)提供任何类型的用户声明的构造函数,编译器将始终将默认构造函数声明为其类的内联公共成员。

相反,如果声明了用户提供的构造函数,则不会定义隐式定义的默认构造函数。

来自[class.ctor]§5

  

类X的默认构造函数是类X的构造函数,可以在没有参数的情况下调用。如果类X没有用户声明的构造函数,则没有参数的构造函数被隐式声明为默认值(8.4)。

由于您的类具有用户提供的构造函数,因此不会生成隐式声明/定义的构造函数。同样,您可以随时使用= default强制它生成。