Почему явные конструкторы не совпадают с аргументами функции, инициализирующей список?

Чтобы проиллюстрировать проблему, давайте рассмотрим эти два простых определения, Bar — это пользовательский тип с явным конструктором из int:

struct Bar
{
    explicit Bar(int a)
    {}
};

void f(Bar)
{}

Теперь, как указано в cppreference:

direct-list-initialization (учитываются как явные, так и неявные конструкторы)

Мы можем инициализировать экземпляр таким образом

Bar b1{5};

Тем не менее, вызов функции таким образом является ошибкой компиляции.

f({5});

Это по-прежнему будет наивно выглядеть как прямая инициализация списка аргумента Bar аргумента f, плюс можно утверждать, что явное использование фигурных скобок вокруг аргумента делает его... явным.

Какова причина запрета использования явного конструктора для аргументов функций, инициализированных списком?

Редактировать

Связанная страница действительно говорит, что в этой ситуации это не инициализация прямого списка. Тем не менее, в духе вопроса, каково было бы обоснование разработки языковых правил, чтобы в этом случае было copy-list-init , а не direct-list-init ?


person Ad N    schedule 16.12.2016    source источник
comment
f({5}) — это инициализация списка копирования.   -  person T.C.    schedule 16.12.2016
comment
@Т.С. Вы правы, это пункт 7) на странице, на которую есть ссылка в вопросе.   -  person Ad N    schedule 16.12.2016


Ответы (1)


Потому что для передачи аргумента функции это не прямая инициализация списка, а инициализация-копии-списка; могут быть вызваны только неявные конструкторы.

function( { arg1, arg2, ... } ) ; (7) 
  • copy-list-initialization (можно вызывать только неявные конструкторы)

7) в выражении вызова функции, где в качестве аргумента используется braced-init-list, а list-initialization инициализирует параметр функции

Обратите внимание, что до C++11 (т.е. несмотря на инициализацию списка функций C++11) передача аргумента функции по значению всегда пересчитывалась как инициализация копированием, а не прямой инициализацией.

person songyuanyao    schedule 16.12.2016
comment
Для инициализации списка копирования явные конструкторы не рассматриваются. Неа. - person T.C.; 16.12.2016
comment
@Т.С. Отличается ли это тем, что можно вызывать только неявные конструкторы? Я что-то пропустил? - person songyuanyao; 16.12.2016
comment
Разница struct A { A(int); explicit A(char); }; A a = 'a' /* OK */, b = {'a'} /* error */; - person T.C.; 16.12.2016
comment
Спасибо за предоставление этой ссылки, которая объясняет, почему наблюдается такое поведение. Тем не менее, есть ли у вас какое-то объяснение относительно обоснования такого определения поведения в языке? - person Ad N; 16.12.2016
comment
@Т.С. Думаю, я понял, что вы имели в виду. - person songyuanyao; 16.12.2016
comment
@AdN Извините, я не могу хорошо объяснить причину; но, несмотря на новую инициализацию списка функций C++11, передача аргумента функции по значению всегда пересчитывается как копировать инициализацию. - person songyuanyao; 16.12.2016