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