I tried compiling this C++ code under GCC 8.2 with different options and it always succeeds, produces no warnings and outputs true
:
int && a = 123;
decltype(auto) b = a;
std::cout << std::boolalpha << std::is_same<decltype(b), int&>::value;
Meanwhile, the same code will not compile in Clang, and if my understanding of the standard is correct, that's the standard-conforming behavior.
cppreference on decltype
:
If the argument is an unparenthesized id-expression or an unparenthesized class member access expression, then decltype yields the type of the entity named by this expression.
cppreference on decltype(auto)
:
If the declared type of the variable is decltype(auto), the keyword auto is replaced with the expression (or expression list) of its initializer, and the actual type is deduced using the rules for decltype.
Therefore, decltype(auto)
should yield int&&
. And since a
is an lvalue, it should not bind to b
, resulting in a compilation error.
So does GCC fail to conform to the standard or is there something I'm missing?
Your reasoning is sound. And I think I see where GCC is tripping.
The wording for decltype(auto)
says that auto
is replaced with the expression in the initializer. Which according to GCC would imply your code is not equivalent to
decltype(a) b = a;
But rather it is equivalent to
decltype((a)) b = a;
But that is wrong. The initializer is "an unparenthesized id-expression", so the rules in [dcl.type.simple] for unparenthesized id-expressions should apply normally. The type of b
needs to be deduced as int&&
.
And as @Aconcagua was able to dig up, this is a known GCC bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With