调用类模板中隐式删除的副本构造函数

问题描述 投票:0回答:1

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

类似:

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

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

我有下面的示例代码再现了我的问题:

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个回答
0
投票

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

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

解决方案:添加副本构造函数(签名:Foo(const Foo<T>&))或删除移动构造函数(即,允许编译器生成副本构造函数)。

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

© www.soinside.com 2019 - 2024. All rights reserved.