Когда аргумент является списком инициализатора ([dcl.init.list]), это не выражение, и для его преобразования в тип параметра применяются специальные правила.
Если тип параметра является агрегатным классом, X а список инициализаторов имеет единственный элемент типа cv U, где U is X или класс, производный от X, неявная последовательность преобразования - это последовательность, необходимая для преобразования элемента в тип параметра.
В противном случае, если тип параметра является символьным массивом,133 а в списке инициализаторов есть единственный элемент, который является строковым литералом соответствующего типа ([dcl.init.string]), неявная последовательность преобразования является преобразованием идентичности.
В противном случае, если тип параметра равен std::initializer_list<X> и все элементы списка инициализатора могут быть неявно преобразованы в X, последовательность неявного преобразования является наихудшим преобразованием, необходимым для преобразования элемента списка в X, или, если список инициализатора не имеет элементов, идентификатор конверсия. Это преобразование может быть определенным пользователем преобразованием даже в контексте вызова конструктора списка инициализаторов. [ Example:
void f(std::initializer_list<int>); f( {} ); // OK: f(initializer_list<int>) identity conversion f( {1,2,3} ); // OK: f(initializer_list<int>) identity conversion f( {'a','b'} ); // OK: f(initializer_list<int>) integral promotion f( {1.0} ); // error: narrowing struct A { A(std::initializer_list<double>); // #1 A(std::initializer_list<complex<double>>); // #2 A(std::initializer_list<std::string>); // #3 }; A a{ 1.0,2.0 }; // OK, uses #1 void g(A); g({ "foo", "bar" }); // OK, uses #3 typedef int IA[3]; void h(const IA&); h({ 1, 2, 3 }); // OK: identity conversion
— end example ]
В противном случае, если тип параметра - «массив из N X», если существует неявная последовательность преобразования для каждого элемента массива из соответствующего элемента списка инициализаторов (или из, {} если такого элемента нет), последовательность неявного преобразования является худшая такая последовательность неявного преобразования.
В противном случае, если параметр не является совокупным учащимся X и Разрешением перегрузки PER [over.match.list] выбирает один лучший конструктором C из X выполнить инициализацию объекта типа X от аргумента инициализатора списка:
Если C это не конструктор списка инициализаторов, а список инициализаторов имеет единственный элемент типа cv U, где U is X или класс, производный от X, неявная последовательность преобразования имеет ранг точного соответствия, если он U есть X, или ранг преобразования, если U является производным от X.
В противном случае неявная последовательность преобразования является пользовательской последовательностью преобразования, а вторая стандартная последовательность преобразования является преобразованием идентичности.
Если жизнеспособны несколько конструкторов, но ни один из них не лучше других, последовательность неявного преобразования является последовательностью неоднозначного преобразования. Пользовательские преобразования разрешены для преобразования элементов списка инициализаторов в типы параметров конструктора, за исключением случаев, указанных в [over.best.ics]. [ Example:
struct A { A(std::initializer_list<int>); }; void f(A); f( {'a', 'b'} ); // OK: f(A(std::initializer_list<int>)) user-defined conversion struct B { B(int, double); }; void g(B); g( {'a', 'b'} ); // OK: g(B(int, double)) user-defined conversion g( {1.0, 1.0} ); // error: narrowing void f(B); f( {'a', 'b'} ); // error: ambiguous f(A) or f(B) struct C { C(std::string); }; void h(C); h({"foo"}); // OK: h(C(std::string("foo"))) struct D { D(A, C); }; void i(D); i({ {1,2}, {"bar"} }); // OK: i(D(A(std::initializer_list<int>{1,2}), C(std::string("bar"))))
— end example ]
В противном случае, если параметр имеет тип агрегата, который может быть инициализирован из списка инициализаторов в соответствии с правилами для aggregate initialization, неявная последовательность преобразования является пользовательской последовательностью преобразования, а вторая стандартная последовательность преобразования является преобразованием идентичности. [ Example:
struct A { int m1; double m2; }; void f(A); f( {'a', 'b'} ); // OK: f(A(int,double)) user-defined conversion f( {1.0} ); // error: narrowing
— end example ]
В противном случае, если параметр является справочным, см [over.ics.ref]. [ Note: Правила в этом разделе будут применяться для инициализации базового временного объекта для ссылки. ] [ — end note Example:
struct A { int m1; double m2; }; void f(const A&); f( {'a', 'b'} ); // OK: f(A(int,double)) user-defined conversion f( {1.0} ); // error: narrowing void g(const double &); g({1}); // same conversion as int to double
— end example ]
В противном случае, если тип параметра не является классом:
если в списке инициализаторов есть один элемент, который сам не является списком инициализаторов, неявная последовательность преобразования является той, которая требуется для преобразования элемента в тип параметра; [ Example:
void f(int); f( {'a'} ); // OK: same conversion as char to int f( {1.0} ); // error: narrowing
— end example ]
если список инициализаторов не имеет элементов, неявная последовательность преобразования является преобразованием идентичности. [ Example:
void f(int);
f( { } ); // OK: identity conversion
— end example ]
Поскольку нет параметров типа массива, это будет происходить только как ссылочный тип ссылочного параметра.