The code follows.
struct A {
A() {}
};
struct B {
B() {}
explicit operator A() { return A{}; }
};
struct C {
A a;
C(B b) : a{b} {}
};
I have a struct A
which is not aggregate constructible (because it has a constructor defined). The same goes for struct B
. But it also has an explicit user-defined conversion operator to struct A
. Now struct C
's constructor takes a struct B
, and uses it to construct struct A
. As on cppreference, the conversion operator can participate in direct initialization, which I believe is the case for the member initialization of struct C
. It passes on GCC 5.2 (C++11). But however it fails on Clang 3.6. I tried with C++11, C++14, and C++1z.
If I change a{b}
to a(b)
, it passes on both Clang and GCC.
I wonder if it is a Clang bug or I misunderstood the standard?
There have been recent changes in clang due to DR1467 (cfr. 22259)
Recent version of gcc and clang both do the right thing: compile your code without errors.
In the first round of overload resolution for the member initializer list A's constructors are discarded since they're not initializer-list constructors.
Afterwards [over.match.list]/p1 takes over
- If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.
and this time A's constructors are kept into account. A's copy and move constructors have enough arguments to match the overload resolution process and they don't cause any user-defined conversion suppression since 13.3.1.3 and even 13.3.1.7 (still in Clang's code) don't apply to these constructors.
Therefore they're entered in the overload resolution set and [over.best.ics] applies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With