【问题标题】:Why is (deleted) copy constructor preferred over implicit conversion?为什么(已删除)复制构造函数优于隐式转换?
【发布时间】:2016-02-20 19:57:18
【问题描述】:

考虑下面的代码:

struct Bar{};

struct Foo
{
    Foo() = default;
    Foo(const Bar&) {}
    Foo(const Foo&) = delete;

    // IMPLICIT conversion to Bar
    operator Bar(){return {};}
};

int main() 
{
    Foo f1;
    Foo f2(static_cast<Bar>(f1)); // this is OK
    Foo f3(f1); // does not compile, why not implicit conversion to `Bar`?
}

Bar 类有一个用户定义的到Foo 的转换运算符,它接受Bar&amp;s。但是,在main 的最后一行中,我希望Foo f1 被转换为Bar,然后传递给Foo(const Bar&amp;)。但是,只考虑删除的构造函数Foo(const Foo&amp;) = delete;。我知道这个构造函数更匹配,但是为什么Foo(const Bar&amp;)不在重载集中,为什么编译器不执行隐式转换?

【问题讨论】:

    标签: c++ implicit-conversion constructor-overloading


    【解决方案1】:

    这是首选,因为查找和重载解决方案发生在已删除的成员函数上记录已删除的定义之前。

    也就是说,重载决议将不考虑 delete 说明符和您的调用:

    Foo f3(f1);
    

    由于f1Foo 类型,Foo(const Foo&amp;) 是直接参数类型匹配。因此,在重载分辨率方面的排名高于Foo(const Bar&amp;)

    【讨论】:

    • 是的,但是如果您有 2 个同样优秀的候选者,其中一个是 deleted,我会希望编译器选择另一个。为什么没有发生这种情况?
    • @vsoftco delete 更像是在说“调用它会失败”,但这并不意味着它不存在。
    • @vsoftco 似乎您正在尝试以与 C++ 定义它们的方式完全不同的方式使用已删除的函数。你所追求的完全有道理,这不是 C++ 的工作方式。给定例如void f(long); void f(int) = delete;f(1) 不起作用,void f(int) = delete; 很可能被添加特别以使f(1) 不起作用。标准库中有这样被删除的重载。根据您想要的规则,f(1) 可以工作,它只会选择 void f(long) 重载。
    • 这很清楚,谢谢。有没有办法从重载候选集中删除一个函数? (虽然=delete 是我第一次这样做)
    • @vsoftco 不,没有办法做到这一点。我的建议是坚持使用static_cast,这样你也可以向阅读代码的人表明你的意图。
    猜你喜欢
    • 1970-01-01
    • 2020-01-14
    • 2015-01-08
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 2018-10-29
    • 2020-10-03
    • 1970-01-01
    相关资源
    最近更新 更多