为什么常量左值引用在重载解析期间优先于常量右值引用
Why const lvalue reference has priority over const rvalue reference during overloading resolution
为什么没有歧义?
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
}
在这里,我想将对B
和C
实例的 lvalue const 引用存储到A
的实例中。当然,我想确保引用对象的生存期克服A
实例的生存期。
为了实现这一点,我只是= delete;
B const &&
和C const &&
的重载,此外,它还相应地匹配B &&
和C &&
。
上述方法非常适合转换构造函数(即一元构造函数)。但事实证明,对于更高的arity,我必须明确= delete;
所有组合上可能的组合,这些组合包含感兴趣参数的常量右值参考版本(即#if 1
)。
然后我想:"为什么没有歧义?"——因为歧义也应该防止在上述情况下编译错误的代码。
所以问题是:"为什么构造函数调用的混合大小写没有歧义?
tl;大卫:它是这样重新设计的。
在最初的移动提案下,您的代码将是模棱两可的。 根据该建议,左值可以绑定到右值引用,但如果重载集中存在左值引用,则更喜欢左值引用。
在这个过程的后期,随着越来越多的人开始理解该提案,并且由于C++11的概念仍在考虑中,规则发生了变化,以便左值无法绑定到右值引用。
我个人认为这种更改没有必要,但喜欢这种更改的人比不喜欢它的人要多得多,并且移动语义的基本功能可以正常工作。 所以这绝对是一个值得做出的妥协,而不是根本没有移动语义。
由于更改了 lvalues 无法绑定到右值引用,如果任一参数是 lvalue,则A(B const &&, C const &&)
不是重载解析集的一部分。 但是,如果其中一个(或两个)参数都是左值,则A(B const &, C const &)
保留在重载集中。
相关文章:
- 什么时候在C++中返回常量引用是个好主意
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 为什么我可以通过引用修改常量返回
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- 将常量指针引用绑定到非常量指针
- 通过常量引用传递参数的矩阵模板类
- 按值捕获引用时出现非常量
- 在C++中使用非常量引用作为常量
- 具有常量引用参数的函数模板专用化
- 多个"常量引用"变量可以共享同一个内存吗?
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 为什么按值传递QStringView比引用常量更快?
- 通过引用常量函数调用另一个类的非常量函数
- 构造常量对象与引用常量对象
- 引用“常量value_type”时出错
- 为什么可以在 for 语句中重新分配引用常量
- 程序反馈:命名循环索引和引用常量数据
- 堆还是栈?在c++中函数调用中引用常量字符串时
- 为什么常量结构数组在按名称引用常量结构时不放在 .rodata 中?
- 为什么编译器允许在函数中发送对迭代器的引用,该函数引用常量迭代器