Что может пойти не так, если при инициализации списка копирования разрешены явные конструкторы?

В стандарте 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

Поскольку запрет прямо заявлен, у меня такое чувство, что я что-то здесь упускаю. Насколько я понимаю, выбор явных конструкторов для инициализации списка не кажется мне проблемой: используя синтаксис инициализации списка, программист уже выражает желание выполнить какое-то «преобразование».

Что могло пойти не так? Что мне не хватает?

38
задан Casey 12 February 2014 в 16:12
поделиться