用户删除的自动构造函数对隐式生成复制构造函数的影响

Effect of user deleted auto constructors on implicit generation of copy constructors

提问人:Sourav Kannantha B 提问时间:2/21/2023 最后编辑:Sourav Kannantha B 更新时间:2/21/2023 访问量:70

问:

用户删除的自动构造函数如何影响复制构造函数的隐式生成? 例如:

struct Foo {
    Foo(X) = delete;
    auto operator=(X) = delete;
};

int main() {
    Foo a;
    Foo b(a);
    b = a;
}

在上面的结构中,如果 X 是 ,则编译器仍然会生成复制构造函数和复制赋值运算符,因此代码的编译和执行完全正常。autoconst auto&const auto&&

但是,如果 X 是或,那么编译器将不会生成复制构造函数和复制赋值运算符,并且我收到“使用已删除函数”错误。auto&auto&&

我已经尝试过 GCC、Clang 和 ICC(不幸的是 MSVC 仍然不支持自动参数),并且在这三个中都观察到相同的行为。所以,我想它在标准中定义的某个地方。

哪个标准规则指导编译器的上述行为?

C++ 构造函数 复制 赋值 deleted-functions

评论

2赞 NathanOliver 2/21/2023
使用(是模板)的构造函数从来都不是复制或移动构造函数。auto
3赞 NathanOliver 2/21/2023
我们有什么方法可以得到一个你想工作但没有的代码的最小可重现的例子吗?最有可能的是,您遇到了首选的情况,因为您正在尝试复制一个非常量左值。auto&
1赞 463035818_is_not_an_ai 2/21/2023
顺便说一句,MSVC 确实支持自动参数,但仅限于 C++20(应该如此)godbolt.org/z/Gnjr7sPse
0赞 Sourav Kannantha B 2/21/2023
@NathanOliver抱歉,我已经用最少的可重复示例更新了这个问题。
1赞 Ted Lyngmo 2/21/2023
在您的示例中,您在构造时传递了一个非左值(就像@NathanOliver猜测的那样)。 和 (=> ) 是更好的匹配,因为它不需要任何转换。constbauto&auto&&Foo&const Foo&

答:

3赞 user17732522 2/21/2023 #1

auto在函数参数中,其含义与将其替换为模板参数完全相同。

例如,

Foo(auto&) = delete;

template <typename T>
Foo(T&) = delete;

模板化构造函数从来都不是复制/移动构造函数,模板化赋值运算符从来都不是复制/移动赋值运算符。

因此,它们根本不影响隐式复制/移动构造函数/赋值操作器的生成。无论您使用 、 、 还是 .仍将生成隐式复制和移动构造函数和赋值运算符。autoconst auto&auto&const auto&&auto&&

但是,用户声明的模板化重载仍参与重载解析,并且在某些情况下,可以根据正常的重载解析规则选择隐式声明的重载。

评论

0赞 Sourav Kannantha B 2/21/2023
我用最少的可重复示例更新了这个问题。查看我收到的错误是否是由于重载解决规则造成的。
1赞 user17732522 2/21/2023
@SouravKannanthaB 是的,因为 / 推导到比 () 类型的非左值的隐式重载更匹配。因为 和 两者都同样好,所以非模板是首选。在 just 的情况下,有一个特殊的规则,即永远不会考虑将采用(cv 限定的)类类型本身的单个参数的构造函数模板专用化(因为它始终是无限递归)。auto&auto&&Foo&const Foo&constFooaconst auto&const auto&&auto