Ответ 1
Я думаю, что этот ответ может быть уместным.
Да, это поведение предназначено, согласно §13.3.1.7 Инициализация по инициализации списка
Когда объекты неагрегатного типа типа T инициализируются списком (8.5.4), разрешение перегрузки выбирает конструктор в две фазы:
- Изначально функции-кандидаты являются конструкторами-инициализаторами-списками (8.5.4) класса T, а список аргументов состоит из список инициализаторов как один аргумент.
- Если не найден жизнеспособный конструктор списка инициализаторов, снова выполняется разрешение перегрузки, где все функции-кандидаты конструкторы класса T и список аргументов состоят из элементы списка инициализаторов.
В gcc
Я попробовал ваш пример. Я получаю эту ошибку:
error: call of overloaded 'A(<brace-enclosed initializer list>)' is ambiguous
gcc
перестает жаловаться, если я использую три набора фигурных скобок. то есть:.
#include <iostream>
#include <vector>
#include <initializer_list>
struct A {
A (std::initializer_list<int> il) {
std::cout << "First." << std::endl;
}
A (std::initializer_list<std::initializer_list<int>> il) {
std::cout << "Second." << std::endl;
}
};
int main()
{
A a{0}; // first
A a{{0}}; // compile error
A a2{{{0}}}; // second
A a3{{{{0}}}}; // second
}
В попытке отразить векторные конструкторы, вот мои результаты:
#include <iostream>
#include <vector>
#include <initializer_list>
struct A {
A (std::initializer_list<int> il) {
std::cout << "First." << std::endl;
}
explicit A (std::size_t n) {
std::cout << "Second." << std::endl;
}
A (std::size_t n, const int& val) {
std::cout << "Third." << std::endl;
}
A (const A& x) {
std::cout << "Fourth." << std::endl;
}
};
int main()
{
A a{0};
A a2{{0}};
A a3{1,2,3,4};
A a4{{1,2,3,4}};
A a5({1,2,3,4});
A a6(0);
A a7(0, 1);
A a8{0, 1};
}
main.cpp:23:10: warning: braces around scalar initializer
A a2{{0}};
^~~
1 warning generated.
First.
First.
First.
First.
First.
Second.
Third.
First.