Подтвердить что ты не робот

Почему std:: stack не использует параметр шаблона шаблона?

Почему std::stack и std::queue используют параметр шаблона типа вместо параметра шаблона шаблона для своего базового типа контейнера?

то есть. почему stack объявлен следующим образом:

template<typename T, typename Container = deque<T>>
class stack;

но не так:

template<typename T, template<typename> class Container = deque>
class stack;

?

4b9b3361

Ответ 1

Потому что типичные контейнеры, такие как std::vector, имеют более одного аргумента шаблона. Не заботясь о том, что это шаблон, вы разрешаете использовать каждый вид контейнера.

Как

template<class T, class Allocator = std::allocator<T>> class vector;

вписывается в

template<typename> class Container

как это было бы в вашем stack? (Подсказка: это не так!) Вам понадобятся специальные случаи для каждого числа и типа аргументов шаблона (тип против не-типа), которые вы хотите поддержать, что глупо, потому что они обычно не вносят никакого вклада больше информации, чем простой

typename Container

Обратите внимание, что для получения фактических аргументов шаблона, например. a std::vector, у вас есть typedefs std::vector::value_type и std::vector::allocator_type, устраняя необходимость использования этих типов в явном виде, где вы действительно используете тип (т.е. Container of stack).

Ответ 2

Вкратце: использование параметра шаблона шаблона является более строгим *, чем использование параметра типа без предоставления каких-либо преимуществ.

* Под ограничением я подразумеваю, что вам может потребоваться более сложный материал для получения тех же результатов, чем с параметром "простого" типа.

Почему нет преимуществ?

Ваш std::stack вероятно, имеет такой атрибут:

template <typename T, typename Container>
struct stack {
    Container container;
};

Если вы замените Container параметром шаблона шаблона, почему вы получили бы?

template <typename T, template <typename...> class Container>
struct stack {
    Container<T> container;
};

Вы создаете экземпляр Container только один раз и только для T (Container<T>), поэтому нет никаких преимуществ для параметра шаблона шаблона.

Почему это более ограничительно?

С параметром шаблона шаблона вы должны передать в std::stack шаблон, который предоставляет такую же сигнатуру, например:

template <typename T, template <typename> class Container>
struct stack;

stack<int, std::vector> // Error: std::vector takes two template arguments

Может быть, вы могли бы использовать шаблоны variadic:

template <typename T, template <typename... > class Container>
struct stack {
    Container<T> container;
};

stack<int, std::vector> // Ok, will use std::vector<int, std::allocator<int>>

Но что, если я не хочу использовать стандартный std::allocator<int>?

template <typename T, 
          template <typename....> class Container = std::vector, 
          typename Allocator = std::allocator<T>>
struct stack {
    Container<T, Allocator> container;
};

stack<int, std::vector, MyAllocator> // Ok...

Это становится немного грязно... Что если я захочу использовать свои собственные шаблоны контейнеров, которые принимают параметры 3/4/N?

template <typename T,
          template <typename... > class Container = std::vector,
          typename... Args>
struct stack {
    Container<T, Args...> container;
};

stack<int, MyTemplate, MyParam1, MyParam2> // Ok...

Но что, если я хочу использовать контейнеры без шаблонов?

struct foo { };
struct foo_container{ };

stack<foo, foo_container> // Error!

template <typename... >
using foo_container_template = foo_container;

stack<foo, foo_container_template> // Ok...

С параметром типа нет таких проблем 1:

stack<int>
stack<int, std::vector<int, MyAllocator<int>>
stack<int, MyTemplate<int, MyParam1, MyParam2>>
stack<foo, foo_container>

1 Существуют и другие случаи, в которых не работает параметр шаблона шаблона, например использование шаблонов, принимающих сочетание типов и не типовых параметров в определенных заказах, для которых вы можете создать универсальный параметр шаблона шаблона, даже используя шаблоны с переменными параметрами.

Ответ 3

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

Ответ 4

Потому что он не компилирует:

std::deque is not type

template <typename T> class std::deque

его тип

template<class T, class Alloc> class std::deque

Это, конечно, более общая проблема: даже если мы должны предоставить параметр шаблона Alloc нашему шаблону класса stack, класс теперь будет работать только с контейнерами, которые имеют ровно два аргумента шаблона типа. Это необоснованное ограничение.