#c #c 11 #stdinitializerlist
Вопрос:
Я передал вложенные списки инициализации в конструктор класса:
#include <iostream>
#include <type_traits>
#include <variant>
#include <vector>
class NestedInteger final {
public:
NestedInteger(int i) : type_(INT), val_int_(i) {}
// NestedInteger(std::initializer_list<NestedInteger> ni) {
template <typename T>
NestedInteger(std::initializer_list<T> ni) {
for (auto it = ni.begin(); it != ni.end(); it ) {
val_vec_.push_back(*it);
}
}
private:
enum { INT, VECTOR } type_;
int val_int_;
std::vector<NestedInteger> val_vec_;
};
int main() {
NestedInteger ni1{1};
NestedInteger ni2{1, 2, 3};
NestedInteger ni3{{1}, 2, 3};
NestedInteger ni4{{1, 2, 3}};
NestedInteger ni5{{1, 2, 3}, {4, 5, 6, 7}};
return 0;
}
И я получил ошибку компиляции:
t.cpp:29:44: error: no matching function for call to ‘NestedInteger::NestedInteger(<brace-enclosed initializer list>)’
29 | NestedInteger ni5{{1, 2, 3}, {4, 5, 6, 7}};
| ^
t.cpp:12:3: note: candidate: ‘template<class T> NestedInteger::NestedInteger(std::initializer_list<_Tp>)’
12 | NestedInteger(std::initializer_list<T> ni) {
| ^~~~~~~~~~~~~
t.cpp:12:3: note: template argument deduction/substitution failed:
t.cpp:29:44: note: candidate expects 1 argument, 2 provided
29 | NestedInteger ni5{{1, 2, 3}, {4, 5, 6, 7}};
...
Я прочитал инициализацию списка в cppreference здесь. И я могу сказать, что выражение относится к первому типу синтаксиса:
T object { arg1, arg2, ... }; (1)
инициализация именованной переменной со списком инициализации (то есть, возможно, пустым списком выражений, заключенным в скобки, или вложенными списками инициализации)
Я не могу понять объяснения этого эффекта.
Не могли бы вы помочь разобраться:
- Какому пункту в объяснении соответствует этот случай?
Это не выведенные контексты, описанные здесь?
Кстати, если я изменю шаблон на определенный тип в качестве прокомментированной строки, ошибка компиляции исчезнет.
Комментарии:
1. Для чего следует
T
сделать вывод{{1, 2, 3}, {4, 5, 6, 7}}
?2. @songyuanyao Я предполагаю, что параметры в скобках не могут быть выведены, поэтому компилятор следует объяснению и, возможно, достигнет фазы: «все конструкторы T участвуют в разрешении перегрузки по набору аргументов, состоящему из элементов списка инициализации, с ограничением, что допускаются только не сужающие преобразования».
3. Да,
T
здесь нельзя сделать вывод. Это может бытьstd::initializer_list<std::vector<int>, std::vector<int>>
, илиstd::initializer_list<std::list<int>, std::list<int>>
и так далее.