继承的构造函数不能用于复制对象

Inherited constructor cannot be used to copy object

提问人:Dr. Gut 提问时间:3/2/2021 最后编辑:Dr. Gut 更新时间:3/3/2021 访问量:121

问:

此程序不编译:

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>();

错误消息说 。现场演示inherited constructor cannot be used to copy object

但是当我们将最后一行更改为此时,它就会编译。

Doh<void> doh;
Doh<void> x1 = doh;
Doh<void> x2 = Derp<void*>();
Doh<void> x3(Derp<void>());

在这三种情况下,可以使用继承的构造函数。为什么?

C++ 继承 复制构造函数

评论

0赞 Scheff's Cat 3/2/2021
多么卑鄙!我在 Compiler Explorer 编译中得到了您的示例:在 Compiler Explorer 上修复了演示。在摆弄了一会儿之后,我将错误减少为对 的已删除副本构造函数的单一抱怨。 不???这是初始化,它似乎导致了一个中间步骤 - 类似于......但是,我无法详细解释这一点。只是我在 VS2013 中有时会遇到类似的问题(并且一直认为这只是因为 VS2013 太老了。Doh<void>DohDerkDoh<void> x = Doh<void>(Derk<void>());
0赞 Jarod42 3/2/2021
请注意,它不是复制构造函数,仍会生成。template <class U> Base(const Base<U>&)Base(const Base<T>&)
0赞 Dr. Gut 3/3/2021
@Jarod42:你说得对。演示

答:

3赞 Jeff Garrett 3/2/2021 #1

因为这就是规定的工作方式。

[over.match.funcs/9] (英语)在构造 cv2 D 类型的对象时,如果参数列表只有一个参数,并且 C 与 P 相关且 P 是 与 D 相关的参考文献。

这里 ,感兴趣的构造函数是 make 的构造函数。该构造函数不可用,并且没有其他构造函数适合。D = Doh<void>C = Base<void>U = voidP = Base<void>

Doh<void> x1 = doh;

这是可以的,因为它使用 的默认复制构造函数。Doh<void>

Doh<void> x2 = Derp<void*>();

这是可以的,因为与 无关引用。Base<void*>Doh<void>

这种语言的“要点”是他们想要排除看起来像复制/移动构造函数的东西。否则,模板构造函数可能是贪婪的,并且比提供或默认的复制/移动构造函数更匹配,这可能会令人惊讶。BaseDerived


更新:

Doh<void> x3(Derp<void>());

这不会声明和初始化 .它声明一个函数返回 a 并接受一个参数,这是一个不接受参数并返回 的函数。这是“最令人烦恼的解析”的典型例子。Doh<void>x3Doh<void>Derp<void>

要声明和初始化 ,可以使用大括号:Doh<void>

Doh<void> x3{Derp<void>()};

这无法按预期编译。