Ori*_*ent 5 c++ constructor rvalue-reference c++11 c++14
为什么没有歧义?
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
}
Run Code Online (Sandbox Code Playgroud)
在这里,我想将lvalue const引用B和C实例存储到实例中A.当然我想确保引用对象的生命周期克服了A实例的生命周期.
为了实现这一点,我只是= delete;超载了B const &&和C const &&,它除了比赛B &&和C &&相应.
上述方法适用于转换构造函数(即一元函数).但事实证明,对于更高的元素,我必须明确= delete;所有组合可能的组合,其中包含感兴趣的参数的const rvalue参考版本(即#if 1).
然后我想:"为什么没有歧义?", - 因为模糊性也应该阻止在上述情况下编译错误的代码.
所以问题是:"为什么对于构造函数调用的混合情况没有歧义?".
tl;博士:这是重新设计的.
在原始移动提案下,您的代码将是模棱两可的.根据该提议,左值可以绑定到右值引用,但如果它存在于重载集中,则更喜欢左值引用.
在这个过程中相当晚,随着越来越多的人开始理解该提议,并且由于C++ 11仍在考虑概念,因此规则被更改,因此左值不能绑定到右值引用.
我个人并不觉得这个变化是必要的,但远远更多的人喜欢变化比不喜欢它,和移动语义的基本功能将工作无论哪种方式.所以这绝对是一个值得做出的妥协,而不是完全没有移动语义.
A(B const &&, C const &&)如果任一参数是左值,则lvalues无法绑定到右值引用的更改不是重载决策集的一部分.但是A(B const &, C const &),如果任一(或两个)参数都是左值,则保留在重载集中.