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 enumerated b(a); , b(const b&) argument {0}.

    • for b(a) works single user defined conversion.

    • for b(const b&), need initialize const 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 candidates b(a); , b(const b&), argument 0. 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). because 0 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

Popular posts from this blog

php - Invalid Cofiguration - yii\base\InvalidConfigException - Yii2 -

How to show in django cms breadcrumbs full path? -

ruby on rails - npm error: tunneling socket could not be established, cause=connect ETIMEDOUT -