这个程序不编译:
template <class T>
struct Base {
Base();
template <class U>
Base(const Base<U>&);
};
template <class T>
struct Doh : Base<T> {
using Base<T>::Base;
};
template <class T>
struct Derp : Base<T> {
using Base<T>::Base;
};
Doh<void> x = Derp<void>();
错误消息说继承的构造函数不能用于复制对象
。 Live demo .
但是当我们将最后一行更改为此时,它会编译。
Doh<void> doh;
Doh<void> x1 = doh;
Doh<void> x2 = Derp<void*>();
Doh<void> x3(Derp<void>());
在这三种情况下,可以使用继承的构造函数。为什么?
最佳答案
因为这就是规定的工作方式。
[over.match.funcs/9] A constructor inherited from class type C ([class.inhctor.init]) that has a first parameter of type “reference to cv1 P” (including such a constructor instantiated from a template) is excluded from the set of candidate functions when constructing an object of type cv2 D if the argument list has exactly one argument and C is reference-related to P and P is reference-related to D.
在这里D = Doh<void>
, C = Base<void>
感兴趣的构造函数是 U = void
的构造函数这使得P = Base<void>
.该构造函数不可用,没有其他构造函数适合。
Doh<void> x1 = doh;
这没问题,因为它使用了 Doh<void>
的默认复制构造函数.
Doh<void> x2 = Derp<void*>();
这没关系,因为 Base<void*>
与 Doh<void>
无关.
这种语言的“要点”是他们想要排除看起来像复制/移动构造函数的东西。 Base
否则模板构造函数可能是贪婪的,并且比提供的或默认的 Derived
更匹配。复制/移动构造函数可能会令人惊讶。
更新:
Doh<void> x3(Derp<void>());
这不会声明和初始化 Doh<void>
.它声明了一个函数 x3
返回 Doh<void>
并接受一个参数,这是一个不接受参数并返回 Derp<void>
的函数.是“最头疼的解析”的典型例子。
声明并初始化一个Doh<void>
,你可以使用大括号:
Doh<void> x3{Derp<void>()};
这无法按预期编译。
关于c++ - 继承的构造函数不能用于复制对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66432181/