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?