【问题标题】:Call to implicitly deleted copy constructor in a class template [duplicate]调用类模板中隐式删除的复制构造函数[重复]
【发布时间】:2019-12-31 09:10:22
【问题描述】:

我已经编写了一个类模板,只想让复制构造函数有条件地可用。为此,我想应用一些 SFINAE 技巧,并且需要将复制构造函数模板化。

类似:

template <typename U = T, std::enable_if_t<std::is_same_v<U, T> && /* conditions on U */> * = nullptr>
Foo(const Foo<U> &);

但是,我遇到了问题,因为我定义了一个普通的移动构造函数,并且编译器抱怨它隐式删除了复制构造函数,因为我的用户定义了移动构造函数。它不想匹配我写的模板化复制构造函数。

我有以下示例代码可以重现我的问题:

template <typename T>
struct Foo final
{
    Foo() = default;

    template <typename U = T>
    Foo(const Foo<U> &);

    Foo(Foo<T> &&);
};

int main()
{
    auto f1 = Foo<int>{};
    auto f2 = Foo<int>{f1};
}

在 Godbolt 上使用 Clang 9.0.0 编译时出现以下错误:

<source>:15:15: error: call to implicitly-deleted copy constructor of 'Foo<int>'
    auto f2 = Foo<int>{f1};
              ^       ~~~~
<source>:9:5: note: copy constructor is implicitly deleted because 'Foo<int>' has a user-declared move constructor
    Foo(Foo<T> &&)
    ^
1 error generated.
Compiler returned: 1

编译错误仅描述了症状,而不是我的实际错误。我通常可以推断出我做错了什么,但在这种情况下,因为在构造函数上使用 SFINAE 对我来说是全新的,我无法找出错误的根本原因。

谁能帮我修复代码以实现我的目标?

【问题讨论】:

    标签: c++ templates c++17 sfinae


    【解决方案1】:

    编译器确实描述了您的实际错误:

    <source>:9:5: note: copy constructor is implicitly deleted because 'Foo<int>' has a user-declared move constructor
    Foo(Foo<T> &&)
    

    解决方案:添加复制构造函数(签名:Foo(const Foo&lt;T&gt;&amp;))或删除移动构造函数(即允许编译器生成复制构造函数)。

    请注意,template &lt;typename U = T&gt; Foo(const Foo&lt;U&gt; &amp;); 不是复制构造函数,因为它是模板化的。复制构造函数不得模板化。

    【讨论】:

    • 你能建议我可以应用的任何技巧来使复制构造函数仅在条件下可用吗?
    • 好建议,谢谢!这清楚地表明我的方法是一个完全的死胡同……希望我们可以很快使用requires 关键字来更优雅地解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-02
    • 2016-04-13
    • 1970-01-01
    • 2015-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多