c++ - Overload resolution gets different result between gcc and clang -
struct { a(int);}; struct b { explicit b(a); b(const b&);}; b b({0});
gcc 5.1.0 gives error
/dev/fd/63:3:8: error: call of overloaded 'b(<brace-enclosed initializer list>)' ambiguous /dev/fd/63:3:8: note: candidates are: /dev/fd/63:2:27: note: b::b(const b&) /dev/fd/63:2:21: note: b::b(a)
while clang 3.6.0 succeeds.
which 1 right? why?
for gcc 5.1.0: http://melpon.org/wandbox/permlink/pve9eyxgu26nex6x
for clang 3.6.0: http://melpon.org/wandbox/permlink/woi1md2dc519spw0
this may similar direct list initialization compiles successfully, normal direct initialization fails, why? gcc , clang same result.
but different question. b(a)
explicit here. gcc , clang different results.
the difference can reduced
struct { explicit a(int); }; struct b { b(int); }; void f(a); void f(b); int main() { f({ 1 }); }
on gcc fails, in accordance standard (which says list initialization, explicit constructors considered - can yield ambiguity - not allowed selected). clang accepts , calls second function.
in case, @columbo says in answer direct list initialization compiles successfully, normal direct initialization fails, why? applies. difference in case, b(const b&);
not anymore acceptable clang because {0} -> b
conversion faced 2 possibilities: explicit constructor or using copy constructor recursively second time. first option, explained above, not considered clang , time explanation @columbo applies , copy constructor cannot used second time because need user defined conversion have single element (here, 0
). in summary, first constructor succeeds , taken.
since understand issue weird overload resolution rules , might not able follow, here's more intuitive explanation. rules active are, in order
b({0})
means goto http://eel.is/c++draft/dcl.init#17 , there http://eel.is/c++draft/over.match.ctor our first or context . 2 constructors enumeratedb(a);
,b(const b&)
argument{0}
.for
b(a)
works single user defined conversion.for
b(const b&)
, need initializeconst b&
brings http://eel.is/c++draft/over.ics.list#8 http://eel.is/c++draft/over.ics.ref#2 (by of http://eel.is/c++draft/dcl.init#dcl.init.list-3 "otherwise, if t reference type, prvalue temporary of type referenced t copy-list-initialized ...") http://eel.is/c++draft/over.best.ics#over.ics.list-6. resulting or context has candidatesb(a);
,b(const b&)
, argument0
. our second or context , copy-list-initialization 13.3.1.7 (as required over.ics.ref#2 , dcl.init.list-3).for
b(a)
, constructor explicit , therefore ignored clang (in contradiction spec) accepted gcc (hence ambiguity).for
b(const b&)
, scenario handled @columbo , therefore user-defined conversion needed forbidden. newer drafts don't have rule anymore (but added back). because0
const b&
normal user-defined conversion (not list initialization), ignore explicit constructor needed conversion anyway (for potential second use of copy constructor), , therefore user-defined conversion wouldn't possible anyway , rule of less significance thought when wrote above shorter summary.
therefore gcc can use explicit constructor directly, , in addition single use of copy constructor. clang, considers using explicit constructor directly, , won't use indirectly copy-list-initialization using copy constructor gcc does. both won't consider using copy constructor second time, , it's irrelevant here.
Comments
Post a Comment