【问题标题】:Inherited constructor cannot be used to copy object继承的构造函数不能用于复制对象
【发布时间】:2021-03-02 01:56:11
【问题描述】:

此程序无法编译:

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 objectLive demo.

但是当我们把最后一行改成这个时,它就可以编译了。

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

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

【问题讨论】:

  • 多么卑鄙!我在 Compiler Explorer 编译时获得了您的示例:Fixed Demo on Compiler Explorer。在摆弄了一段时间后,我将错误减少为对 Doh&lt;void&gt; 的已删除复制构造函数的单一抱怨。 Doh不是Derk???初始化似乎导致了一个中间步骤 - 类似于 Doh&lt;void&gt; x = Doh&lt;void&gt;(Derk&lt;void&gt;());... 但是,我无法详细解释这一点。只是我有时在 VS2013 中遇到了类似的问题(并且一直认为这只是因为 VS2013 太老了。);-)
  • 请注意template &lt;class U&gt; Base(const Base&lt;U&gt;&amp;) 不是复制构造函数,Base(const Base&lt;T&gt;&amp;) 仍会生成。
  • @Jarod42:你是对的。 Demo.

标签: c++ inheritance copy-constructor


【解决方案1】:

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

[over.match.funcs/9] 从类类型 C ([class.inhctor.init]) 继承的构造函数具有类型“对 cv1 P 的引用”的第一个参数(包括从模板实例化的这种构造函数)被排除在集合之外构造类型为 cv2 的对象时的候选函数的数量 D 如果参数列表只有一个参数并且 C 是 reference-related 到 P 并且 P 是 与 D 相关的参考文献。

这里是D = Doh&lt;void&gt;C = Base&lt;void&gt;,感兴趣的构造函数是带有U = void的构造函数,它构成P = Base&lt;void&gt;。该构造函数不可用,没有其他适合。

Doh<void> x1 = doh;

这没关系,因为它使用Doh&lt;void&gt;的默认复制构造函数。

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

这没关系,因为 Base&lt;void*&gt;Doh&lt;void&gt; 没有引用相关。

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


更新:

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

这不会声明和初始化Doh&lt;void&gt;。它声明了一个函数x3,返回一个Doh&lt;void&gt;,并接受一个参数,该参数是一个不接受参数并返回Derp&lt;void&gt;的函数。这是“最令人头疼的解析”的典型例子。

要声明和初始化Doh&lt;void&gt;,可以使用大括号:

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

这无法按预期编译。

【讨论】:

    猜你喜欢
    • 2015-04-11
    • 2012-09-20
    • 2015-03-27
    • 2019-01-12
    • 2012-01-29
    • 2014-12-27
    相关资源
    最近更新 更多