为什么const over值引用在重载分辨率期间优先于const rvalue引用

时间:2016-12-23 13:29:26

标签: c++ c++11 constructor c++14 rvalue-reference

为什么没有歧义?

struct B {};
struct C {};

struct A
{
    A(B const &, C const &) {}
    A(B const &&, C const &&) = delete;
#if 0
    A(B const &, C const &&) = delete;
    A(B const &&, C const &) = delete;
#endif
};

B const b() { return {}; } // const result type may make sense
C const c() { return {}; } // for some user-defined types

int main()
{
    A a0{B{}, C{}}; // I want to prohibit this
    A a1{b(), c()}; // and this cases
    B const bb{};
    C const cc{};
    A a2{b(), cc}; // But surely I also want to prohibit this
    A a3{bb, c()}; // and this cases to compile
}

这里我想将BC实例的左值const引用存储到A的实例中。当然,我想确保,引用对象的生命周期克服了A实例的生命周期。

要实现此目的,= delete;B const &&只会C const &&重叠,此外还会匹配B &&C &&

上述方法适用于转换构造函数(即一元函数)。但事实证明,对于更高的灵魂,我必须明确= delete;所有组合可能的组合,其中包含感兴趣的参数的常量参考版本(即#if 1)。

然后我想:"为什么没有含糊不清?", - 因为在上述情况下,歧义也应该阻止编译错误的代码。

所以问题是:"为什么对于构造函数调用的混合情况没有歧义?"。

1 个答案:

答案 0 :(得分:5)

tl; dr:重新 - 这样设计。

the original move proposal下,您的代码不明确。根据该提议,lvalues 可以绑定到右值引用,但如果它存在于重载集中,则更喜欢左值引用。

在此过程中相当晚,随着越来越多的人开始理解该提案,并且正在考虑C ++ 11的概念,the rules were changed so that lvalues could not bind to rvalue references

我个人并不觉得这种变化是必要的,但更多人喜欢这种变化而不喜欢它,移动语义的基本功能无论如何都会起作用。所以这绝对是一个值得做出的妥协,而不是完全没有移动语义。

如果 参数是左值,则lvalues无法绑定到右值引用的更改,A(B const &&, C const &&)不是重载决策集的一部分。但是,如果任一(或两个)参数都是左值,则A(B const &, C const &)仍保留在重载集中。

相关问题