https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98554

            Bug ID: 98554
           Summary: why the explicit conversion function of derived class
                    return type is not a candidate in the context of
                    direct-initialization
           Product: gcc
           Version: 10.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: xmh970252187 at gmail dot com
  Target Milestone: ---

#include <iostream>
struct A{
    A() = default;
    A(A const&){}
};
struct B:A{};
struct C{
    explicit operator B(){
        return B{};
    }
};

int main(){
   C c;
   A a(c);  // #1
}

In this example, GCC reports an error and the note is:  

return type 'B' of explicit conversion function cannot be converted to 'const
A' with a qualification conversion 

The restriction for the second standard conversion of explicit conversion
functions which shall be a qualified conversion is defined in the section
[over.match.conv#1](https://eel.is/c++draft/over.match.conv#1). However, that
section totally says about the initialization for an object of **non-class**
type.  In this example, the candidate functions should obey the rule defined in
section [over.match.copy#1](https://eel.is/c++draft/over.match.copy#1), the
relevant rule is: 
> When the type of the initializer expression is a class type “cv S”, 
> conversion functions are considered. The permissible types for non-explicit 
> conversion functions are T and any class derived from T. When initializing a 
> temporary object ([class.mem]) to be bound to the first parameter of a 
> constructor where the parameter is of type “reference to cv2 T” and the 
> constructor is called with a single argument in the context of 
> direct-initialization of an object of type “cv3 T”, the permissible types for 
> explicit conversion functions are the same; otherwise there are none.

In this example, the object be direct-initialized is the `a` at #1, which has
class type `A`, and the initializer is object `c` whose type is `C`. First, in
order to initialize the object `a`, the following rule will be applied to
>Otherwise, if the initialization is direct-initialization, or if it is 
>copy-initialization where the cv-unqualified version of the source type is the 
>same class as, or a derived class of, the class of the destination, 
>constructors are considered. The applicable constructors are enumerated 
>([over.match.ctor]), and the best one is chosen through overload resolution 
>([over.match]).   

Here, `A(A const&)` is a candidate function and its parameter is of type
"reference to cv2 A", so the explicit conversion functions of class `C` should
be considered. And the standard says "the permissible types for explicit
conversion functions are the same". So in this context, `explicit operator B()`
should be used in the conversion sequence. Moreover, since a conversion
function whose return type is A can be used in this context, why wouldn't B
which is derived A be. Isn't B is-A?

Reply via email to