在查看一些代码时,我遇到了下面一行的结构:
if (const auto& foo = std::get_if<MyType>(&bar)) // note the ampersand!
其中bar
是std::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
是什么类型?
答案 0 :(得分:10)
请注意,对于const auto& foo
,const
在auto
部分是合格的,即指针而不是指针。然后foo
的类型将是Foo* const &
,这是对const
的引用(指向非const
Foo
的指针) ,但不是const Foo* &
,它是对非const
(指向const
Foo
的指针的引用)。
对const
的左值引用可以绑定到f()
返回的右值,因此const auto& foo = f();
可以正常工作; const Foo*& bar = f();
不起作用,因为bar
是对非const
的左值引用;不能绑定到右值。将bar
的类型更改为const Foo * const &
或Foo* const &
(与foo
相同)即可。