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

Reply via email to