Что может пойти не так, если инициализация копирования списка позволила явные конструкторы?
В стандарте C ++, §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
Так как запрет явно указан, у меня такое ощущение, что я что-то здесь упускаю. Насколько я вижу, явные конструкторы выбора инициализации списка не кажутся мне проблемой: используя синтаксис инициализации списка, программист уже выражает желание выполнить какое-то «преобразование».
Что может пойти не так? Что мне не хватает?