Very strange overload failure

  • A+
Category:Languages

I have encountered a very strange overload failure. I am able to isolate the problem, but I cannot for the life of it figure out what goes wrong.

The code is the following

#include <vector> #include <iostream>  template<class X> class Foo { public:   Foo(const std::initializer_list<X> &A){}   Foo(size_t n){} };  class Bar { public:   Bar() = default;   Bar(const Foo<size_t> &A, bool a=true, bool b=true){}; };  int main() {   Bar A({1,2}); } 

Compiling results in

$ clang++ -std=c++14 so.cpp  so.cpp:21:11: error: call to constructor of 'Bar' is ambiguous       Bar A({1,2});           ^ ~~~~~ so.cpp:12:11: note: candidate is the implicit move constructor     class Bar           ^ so.cpp:12:11: note: candidate is the implicit copy constructor so.cpp:16:7: note: candidate constructor       Bar(const Foo<size_t> &A, bool a=true, bool b=true){};       ^ 1 error generated. 

The two things that get rid of the problem are:

  • Removing Foo(size_t n).
  • Changing the constructor to Bar(const Foo<size_t> &A).

Obviously I want to keep all features. So: What goes wrong? How can I solve it?

 


What goes wrong?

Bar A({1,2}); 

Can be interpreted as:

Bar A(Bar{Foo<std::size_t>(1), (bool)2 /*, true*/ }); 

or

Bar A(Foo<std::size_t>{1,2} /*, true, true*/); 

so ambiguous call.

How can I solve it?

It depends of which result you expect, adding explicit might help for example.

Making explicit Foo(size_t n) would allow only:

Bar A(B{Foo<std::size_t>(1), (bool)2 /*, true*/ }); 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: