В стандарте С++, §13.3.1.7 [over.match.list], указано следующее:
В инициализации списка копий, если выбран конструктор
explicit
, инициализация плохо сформирована.
Вот почему мы не можем сделать, например, что-то вроде этого:
struct foo {
// explicit because it can be called with one argument
explicit foo(std::string s, int x = 0);
private:
// ...
};
void f(foo x);
f({ "answer", 42 });
(Обратите внимание, что здесь происходит не преобразование, и это было бы не так, даже если конструктор был "неявным". Это инициализация объекта foo
, используя его конструктор напрямую. Помимо std::string
здесь нет преобразования.)
Это кажется мне совершенно прекрасным. Нет никакого способа, чтобы неявное преобразование укусит меня.
Если { "answer", 42 }
может инициализировать что-то еще, компилятор не выдаст меня и не сделает ничего:
struct bar {
// explicit because it can be called with one argument
explicit bar(std::string s, int x = 0);
private:
// ...
};
void f(foo x);
void f(bar x);
f({ "answer", 42 }); // error: ambiguous call
Нет проблем: вызов неоднозначен, код не будет компилироваться, и я должен будет явно явно перегрузить.
f(bar { "answer", 42 }); // ok
Поскольку запрет явно указывается, у меня такое ощущение, что я что-то упустил. Насколько я могу судить, инициализация списка, создающая явные конструкторы, для меня не кажется проблемой: с помощью синтаксиса инициализации списка программист уже выражает желание сделать какое-то "преобразование".
Что может пойти не так? Что мне не хватает?