Reputation: 407
I'm looking at the standard 5.16 paragraph 3, trying to understand what is going on. Consider the type M
defined as
struct M {
M();
M(const M&);
M(M&&);
};
If I have a ternary expression pred ? E1 : E2
, where the type of E1
is const M&
and the type of E2
is M&&
does 5.16 paragraph 3 bullet 1 apply?
— 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.
I think it doesn't, because to have an implicit conversion to const M&
, which requires M
to have the member function operator const M&()
.
However, I'm not sure, because it could be converted to const M
implicitly, can the reference be implicitly added?
If it is implicitly convertible, does M&&
bind directly to const M&
?
I went through the procedure in 8.5.3, and I think that paragraph 5 bullet 2 is where this case falls, so it does bind directly, but I'm not certain.
— If the initializer expression [..] has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be implicitly converted to an xvalue, class prvalue, or function lvalue of type “cv3 T3”, where “cv1 T1” is reference-compatible with “cv3 T3”
Upvotes: 4
Views: 513
Reputation: 119124
You don't have expressions of type M&&
, instead it would be adjusted to be an xvalue of type M
.
So the question is: if you have an xvalue of type M
, can it be implicitly converted to lvalue reference to const M
? The answer is yes, since a const lvalue reference can be initialized with an rvalue. Such a reference binding is direct since it falls under the following case:
If the initializer expression — is an xvalue (but not a bit-field), class prvalue, array prvalue or function lvalue and “cv1
T1
” is reference-compatible with “cv2T2
”, ...
rather than the last case that involves construction of a temporary, which is the indirect binding case.
Therefore this use of the conditional operator will be well-formed. The xvalue of type M
will be converted to an lvalue of type const M
. Then the lvalue-to-rvalue conversion will be applied and the result will be a prvalue of type const M
.
Upvotes: 5