常量自动引用绑定到(空)指针 - 实际类型是什么?

const auto reference binding to (null) pointer - what is the actual type?

在查看一些代码时,我遇到了一个包含以下行的结构:

if (const auto& foo = std::get_if<MyType>(&bar)) // note the ampersand!

其中 barstd::variant<MyType, OtherType>。这里的问题是 get_if may return a null pointer 我不明白为什么这个语句有效。

考虑这个类似的 MCVE:

#include <iostream>

struct Foo { int a = 42; };

Foo* f() { return nullptr; }

int main() {
    const auto& foo = f();          // Returns a nullptr that binds to Foo*& - UB?
    //static_assert(std::is_same<decltype(foo), const Foo*&>::value); // -> Fails
    //const Foo*& bar = f(); // -> Fails

    if (foo)    std::cout << foo->a << std::endl;
    else        std::cout << "nullpointer" << std::endl;
}

main() 的第一行工作正常,我希望 bar 的类型是 const Foo*&,但静态断言失败。毫不奇怪,以下行也无法通过 cannot bind non-const lvalue reference of type 'const Foo*&' to an rvalue of type 'const Foo*'.

进行编译

main 的第一条语句发生了什么?这个 UB 或标准是否包含一些允许它合法的隐藏秘密? bar 的类型是什么?

请注意,对于 const auto& fooconstauto 部分是限定的,即指针而不是指针。那么 foo 的类型将是 Foo* const &,这是对 const 引用(指向非 const Foo),但不是 const Foo* &,这是对非 const 引用(指向 const Foo 的指针)。

而 lvalue-reference 到 const 可以绑定到 f() 返回的右值,所以 const auto& foo = f(); 工作正常; const Foo*& bar = f(); 不会工作,因为 bar 是 lvalue-reference 到非 const;不能绑定到右值。将 bar 的类型更改为 const Foo * const &Foo* const &(与 foo 相同)将使它起作用。