std :: initializer_list в качестве аргумента шаблона для конструктора

Рассмотрим класс, который наследуется от стандартного контейнера с конструктором шаблона, который вызывает базовый конструктор контейнера. Этот конструктор шаблона работает для простого конструктора копирования и перемещения, но не для ctor initializer_list.

template<typename container_T>
class test : public container_T {
public:
using container_type = container_T;

test() {}

// templated constructor
template<typename T>
test(T t)
: container_T(t) {}

// without this it won't compile
test(std::initializer_list<typename container_T::value_type> l)
: container_T(l) {}
};

int main() {
test<std::deque<int>> vdi1;
test<std::deque<int>> vdi2({1,2,3,4,5,6,7,8,9});

std::cout << "vdi2 before:" << std::endl;
for(auto it : vdi2)
std::cout << it << std::endl;

test<std::deque<int>> vdi3(std::move(vdi2));

std::cout << "vdi2 before:" << std::endl;
for(auto it : vdi2)
std::cout << it << std::endl;

std::cout << "vdi3 before:" << std::endl;
for(auto it : vdi3)
std::cout << it << std::endl;

return 0;
}

Если я удалю initializer_list конструктор vdi2 не скомпилируется. Итак, мой вопрос: почему initializer_list не выводится конструктором шаблона? И возможно ли это сделать?

4

Решение

почему initializer_list не выводится шаблонным конструктором?

Причина в том, что {1,2,3,4,5,6,7,8,9} это просто синтаксическая конструкция, которая не имеет типа. Следовательно, компилятор не может вывести тип T для этой синктической конструкции и первый конструктор не удается.

Однако по специальным стандартным правилам std::initializer_list<T> (среди прочего) может быть построен из этой синктической конструкции и T можно вывести на int, Следовательно, второй конструктор работает.

По ограничению с выводом типа аргумента шаблона функции, с

auto x = {1,2,3,4,5,6,7,8,9};

компилятор устанавливает тип x как std::initializer_list<int>, Есть также специальные Стандартные правила, которые говорят, что так должно быть. Строго говоря, это не вычет типа, потому что, как сказано выше, {1,2,3,4,5,6,7,8,9} не имеет типа для вывода. (Единственный тип вывода происходит здесь T = int в std::initializer_list<T>.) Здесь компилятор выбирает (он не выводит) тип x быть std::initializer_list<int>, В любом случае, нет ничего плохого в том, чтобы злоупотреблять языком, говоря, что тип x выводится std::initializer_list<int>,

Наконец, как отметил DyP в комментариях, вам, вероятно, нужно наследовать все конструкторы (не только те, которые принимают один аргумент) от базового класса контейнера. Вы можете сделать это, удалив все имеющиеся у вас конструкторы и добавив только эту строку в test:

using container_type::container_type;
7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]