当存在模板复制ctor时,不会生成默认ctor

1 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);
}
Run Code Online (Sandbox Code Playgroud)

此代码将无法编译.但如果你取消注释MyClass()= default,那么一切都很好.据我记得模板ctor没有阻止编译器生成默认的ctor和复制ctor.事实上,编译器只在尝试通过默认ctor创建对象时抱怨,而不是复制构造(在这种情况下是编译器生成).代码是用g ++ 5.4.0和7.1.0编译的.两者的行为相同

Gui*_*cot 7

这不是复制构造函数:

template<class X>
MyClass(MyClass<X>& other) {
    val = other.getVal();
}
Run Code Online (Sandbox Code Playgroud)

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

这是一个复制构造函数:

MyClass(const MyClass&) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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

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

从cppreference:

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

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

来自[class.ctor]§5:

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

由于您的类具有用户提供的构造函数,因此不会生成隐式声明/定义的构造函数.再一次,你可以随时强迫它生成= default.