c++ - 为什么 const 左值引用在重载解析期间优先于 const 右值引用

标签 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 实例的左值常量引用存储到 A 的实例中。当然,我想确保引用对象的生命周期超过 A 实例的生命周期。

为了实现这一点,我只是 = delete; B const &&C const && 的重载,另外匹配 B &&C && 对应。

上述方法非常适合转换构造函数(即一元构造函数)。但事实证明,对于更高的参数,我必须显式地 = delete; 所有组合上可能的组合,其中包含感兴趣参数的 const 右值引用版本(即 #if 1).

然后我想:“为什么没有歧义?”,——因为在上述情况下歧义还应该防止编译错误代码。

所以问题是:“为什么构造函数调用的混合大小写没有歧义?”。

最佳答案

tl;dr:以这种方式重新设计。

the original move proposal你的代码会模棱两可。根据该提案,左值可以绑定(bind)到右值引用,但如果它存在于重载集中,则更喜欢左值引用。

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

我个人并不认为这种改变是必要的,但是 喜欢这种改变的人比不喜欢它的人多得多,并且移动语义的基本功能可以以任何一种方式发挥作用。所以这绝对是一个值得做出的妥协,而不是根本没有移动语义。

由于左值不能绑定(bind)到右值引用,A(B const &&, C const &&) 不是重载决议集的一部分,如果任一个参数是一个左值。但是,如果其中一个(或两个)参数是左值,则 A(B const &, C const &) 仍保留在重载集中。

关于c++ - 为什么 const 左值引用在重载解析期间优先于 const 右值引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41302383/

相关文章:

c++ - std::ostringstream 覆盖初始化字符串

c++ - 模板中类的构造函数

c++ - 如何为我自己的 shared_ptr 实现自己实现别名构造函数?

c++ - 在编译时检测处理器是否有 RDTSCP

c++ - 使用 C++ 自动完成(不适用于 Shell)

c++ - 如何将来自用户定义文字的可变字符模板参数转换回数字类型?

c++ - C 字符串堆栈分配

c++ - 使用函数尝试 block 从构造函数中抛出两次异常

c++ - 从成员中查找结构基地址的标准方法

c++ - 哪个进程拥有给定端口(Linux 内核)?