Should this program output 0 or 1? In my reading and understanding of the cited paragraphs from the C++14 standard, it should print 1, but both GCC and clang prints 0 (because the deduced type is A const
instead of A const&
):
#include <iostream>
struct A {};
int main()
{
A a;
A const& ra = std::move(a); // #1
std::cout << std::is_same<decltype(true ? ra : std::move(a)),
A const&>::value; // Prints 0
}
In this case, ra
is a A const
lvalue, and std::move(a)
is a A
xvalue, both of class-types. According to the standard about the conditional operator (emphasis mine), the result should be an lvalue
of type A const
, and thus the decltype
result must be A const&
:
[expr.cond]/3 Otherwise, if the second and third operand have different types and either has (possibly cv-qualified) class type, or if both are glvalues of the same value category and the same type except for cv-qualification, an attempt is made to convert each of those operands to the type of the other. The process for determining whether an operand expression E1 of type T1 can be converted to match an operand expression E2 of type T2 is defined as follows:
— If E2 is an lvalue: E1 can be converted to match E2 if E1 can be implicitly converted (Clause 4) to the type “lvalue reference to T2”, subject to the constraint that in the conversion the reference must bind directly (8.5.3) to an lvalue.
[...]
In this case, E2 is ra
, which is a lvalue, and the other can be implicitely converted to "lvalue reference to T2", as shown in line // #1
. "lvalue reference to T2" is translated as A const&
, so, std::move(a)
binds directly to a lvalue of type A const
, and after the conversion, both operands have same type and value category, and thus:
[expr.cond]/3 If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category [...].
So, the operator result should be an lvalue and the decltype
result should be a reference, and thus the program should print 1.
std::common_type
, no? or at least, the default implementation: en.cppreference.com/w/cpp/types/common_type – Chris Beck