Consider this code:
int **p = 0;
class S {
public:
explicit operator int**&() {
return p;
}
};
int main() {
S a;
int *const*&b (a); // error in both g++-7 and clang-5.0 with "-std=c++17"
return 0;
}
You will agree
- a qualification conversion from
int**
toint*const*
is possible, and int *const*&b (a)
is a direct-initialization.
First, we refer to 11.6.3, paragraph 5 [dcl.init.ref] from n4700.
A reference to type “cv1
T1 (= int*const*)
” is initialized by an expression of type “cv2T2 (= S)
” as follows:
- If the reference is an lvalue reference and the initializer expression
- ...
- has a class type (i.e.,
T2
is a class type), whereT1
is not reference-related toT2
, and can be converted to an lvalue of type “cv3T3
”, where “cv1T1
” is reference-compatible with “cv3T3
” (this conversion is selected by enumerating the applicable conversion functions (16.3.1.6) and choosing the best one through overload resolution (16.3)),then the reference is bound to the initializer expression lvalue in the first case and to the lvalue result of the conversion in the second case...
Here, we expect T3
to be int*const*
. As noted above, whether it's a possible conversion is determined as per 16.3.1.6, paragraph 1 [over.match.ref].
... Assuming that “reference to cv1
T
” is the type of the reference being initialized, and “cvS
” is the type of the initializer expression, withS
a class type, the candidate functions are selected as follows:
- ... For direct-initialization, those explicit conversion functions that are not hidden within
S
and yield type “lvalue reference to cv2T2
” or “cv2T2
” or “rvalue reference to cv2T2
”, respectively, whereT2
is the same type asT
or can be converted to typeT
with a qualification conversion are also candidate functions.
Here, S::operator int**&
yields "lvalue reference to T2 (= int**)
", and it can be converted to T (= int*const*)
by a qualification conversion. Here, we can say that the conversion is possible, but the program is not accepted in both g++-7 and clang-5.0. Why is that?
int& a = 1;
fails to compile, but I don't know the standard enough to quote any specific paragraph. – Rakete1111int**
, but you needint *const*
, and so a conversion happens. – Rakete1111... the Qualification Adjustments do not change the value category or data representation of the type; ...
– b1subint a = 1; double d = a;
, thea
is promoted to a prvaluedouble
. – Rakete1111