Очень странный отказ от перегрузки

Я столкнулся с очень странным перегрузкой. Я могу изолировать проблему, но я не могу в жизни понять, что пошло не так.

Код следующий:

#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});
}

Составление результатов в

$ 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.

Две вещи, которые избавляются от проблемы:

  • Удаление Foo(size_t n).
  • Изменение конструктора на Bar(const Foo<size_t> &A).

Очевидно, я хочу сохранить все функции. Итак: Что не так? Как я могу это решить?

Ответы

Ответ 1

Что пошло не так?

Bar A({1,2});

Может интерпретироваться как:

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

или же

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

так неоднозначный вызов.

Как я могу это решить?

Это зависит от результата, которого вы ожидаете, например, добавление explicit может помочь.

Создание explicit Foo(size_t n) позволило бы:

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