why the explicit conversion function of derived class return type is not a candidate in the context of direct-initialization

Viewed 256

Given the following example:

#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
}

GCC and Clang both report that c cannot be converted to const A&. However, there's a relevant rule in the standard says, explicit operator B() should be a candidate function in this context. That is:
over.match.copy#1.2

When initializing a temporary to be bound to the first parameter of a constructor where the parameter is of type “reference to possibly cv-qualified T” and the constructor is called with a single argument in the context of direct-initialization of an object of type “cv2 T”, explicit conversion functions are also considered. Those that are not hidden within S and yield a type whose cv-unqualified version is the same type as T or is a derived class thereof are candidate functions.

Moreover, in the current standard, the relevant rule still has the same meaning:
over.match.copy#1.2

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.

Regardless of c++17 standard or the current standard, they all say that in the context likes #1, the explicit conversion function that has the return type of class T or any class derived from T is also a candidate.

In my example, The object a of type A is direct-initialized by the single initializer c, which is the single argument in the invocation of constructor, the copy constructor of A has a parameter A const&. In this case, c should be used to initialize a temporary object to be bound to the first parameter. Hence, in this case explicit operator B() should be considered as a candidate function. However, GCC and Clang both reject this example. GCC obviously report a dignosis information that make no sense.
Is it a bug of these compilers? Or, I misunderstand something?

0 Answers
Related