https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83615
Bug ID: 83615 Summary: A reference binding involving a qualification conversion is rejected Product: gcc Version: 7.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: iluvtrollhd at gmail dot com Target Milestone: --- The following code is rejected with "g++-7 -std=c++17 ./main.cpp", but it's well-formed as per the standard (in fact, clang-5.0 accepts it). ---------------------- class S { public: explicit operator int**() { return 0; } }; int main() { S val; int *const*&&ref (val); return 0; } ---------------------- The relevant paragraph in *n4700 is 16.3.1.6, paragraph 1 [over.match.ref]: ---------------------- ... Assuming that “reference to cv1 T” is the type of the reference being initialized, and “cv S” is the type of the initializer expression, with S 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 cv2 T2” or “cv2 T2” or “rvalue reference to cv2 T2”, respectively, where T2 is the same type as T or can be converted to type T with a qualification conversion (7.5), are also candidate functions. ---------------------- Since a second standard conversion consisting of only a qualification conversion from int** to int*const* is possible, `S::operator int**` shall be a candidate function. Furthermore, the result of this implicit conversion sequence is a prvalue, and the temporary materialization conversion is applied so that the reference binds to this xvalue, as per 11.6.3, paragraph 5 [dcl.init.ref]: ---------------------- Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference. - 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 converted to an rvalue or function lvalue of type “cv3 T3”, where “cv1 T1” is reference-compatible with “cv3 T3” (see 16.3.1.6), ... If the converted initializer is a prvalue, its type T4 is adjusted to type “cv1 T4” (7.5) and the temporary materialization conversion (7.4) is applied. In any case, the reference is bound to the resulting glvalue (or to an appropriate base class subobject). *n4700 : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4700.pdf