代码之家  ›  专栏  ›  技术社区  ›  Jimbo

为什么具有复制构造函数和删除的移动构造函数的类不能转换为自身?

  •  3
  • Jimbo  · 技术社区  · 1 年前

    查询“is_convertible_v move constructor deleted”和“c++deleted move construction makes class not converted to self”,所以我希望我没有复制已经回答过的东西。。。来了。。。

    我有以下课程:

    #include <type_traits>
    
    struct OnlyCopyable {
        OnlyCopyable()  { }
        ~OnlyCopyable()  { }
        OnlyCopyable(const OnlyCopyable &src) { }
        OnlyCopyable& operator=(const OnlyCopyable &other) { return *this; }
        OnlyCopyable(OnlyCopyable &&other) = delete;
        OnlyCopyable& operator=(OnlyCopyable &&other) = delete;
    
    };
    
    static_assert(std::is_convertible_v<OnlyCopyable, OnlyCopyable>);
    

    它似乎无法自我转换。这是为什么?

    如果我注释掉那些明确删除移动运算符的行,它就会变得可转换。为什么?

    CPP参考 this to say :

    如果虚函数定义 To test() { return std::declval<From>(); } 结构良好(即 std::declval<From>() 可以转换为 To 使用隐式转换,或两者兼而有之 From 可能符合简历资格 void ),提供等于的成员常数值 true

    我认为这意味着一个只有复制构造函数的类应该可以转换为自身。。。我错过了什么?谢谢。

    编辑:

    我进一步调查了一下,并根据上述引文定义了以下内容:

    OnlyCopyable test() { return std::declval<OnlyCopyable>(); }
    

    低,看哪,这不适用于错误消息 error: use of deleted function 'OnlyCopyable::OnlyCopyable(OnlyCopyable&&)' .

    我可以理解上面失败的原因,因为删除的运算符仍然会参与过载解析,如果选择,则会导致失败。

    但这仍然让我感到困惑。。。为什么可兑换性是这样定义的?当然,这门课还是可以转换的。。。只是通过复制而不是移动?

    1 回复  |  直到 1 年前
        1
  •  2
  •   Caleth    1 年前

    但这仍然让我感到困惑。。。为什么可兑换性是这样定义的?当然,这门课还是可以转换的。。。只是通过复制而不是移动?

    我认为这是荒谬的 1. 一个类是可复制的,但不能移动,所以这不是标准应该关心的情况。测试” To test() { return std::declval<From>(); } “结构良好” 简单的 ,这种简单性是有价值的。

    由于左值到右值的转换,右值比左值更通用。

    如果不定义移动构造函数,则重载解析会选择复制构造函数作为最佳可行函数。相反,你有 = delete d它,这会使它处于过载解析状态,并在选择它作为最佳可行函数时导致错误。

    1. 您始终可以从副本合成移动,因为参数在正文中变为左值。与不声明move相比,这并没有什么作用,因为右值无论如何都会绑定到const左值引用。
    struct ExplicitMove {
        ExplicitMove(const ExplicitMove &src);
        ExplicitMove& operator=(const ExplicitMove &other);
        ExplicitMove(ExplicitMove &&other) : ExplicitMove(other) {}
        ExplicitMove& operator=(ExplicitMove &&other) { return *this = other; }
    
        // Other members...
    };