Во-первых, это будет std::vector
, и ничего больше, потому что vector
находится в пространстве имен std
, и вы запрашиваете параметр шаблона шаблона , тогда как std::vector<int>
не является шаблон больше. Затем std::vector
фактически принимает два параметров шаблона, один для типа и другой для распределителя:
template <
typename T,
template<typename, typename> class ContainerType,
typename Alloc = std::allocator<T>
>
class Stack{
ContainerType<T, Alloc> container;
// ...
};
// usage:
Stack<int, std::vector> s;
Теперь, это разрешает только контейнеры с двумя параметрами шаблона в качестве базового типа, поэтому вам лучше с тем, что делает стандарт: воспринимайте его как нормальный тип:
template <typename T, typename ContainerType>
class Stack{
ContainerType container;
// ...
};
// usage:
Stack<int, std::vector<int> > s;
Чтобы гарантировать, что базовый тип имеет тот же T
, вы можете сделать поддельное «статическое утверждение» или, если у вас есть компилятор с поддержкой C ++ 0x, вы можете сделать фактическое статическое утверждение:
#include <tr1/type_traits> // C++03 us std::tr1::is_same
//#include <type_traits> // C++0x, use std::is_same
template <typename T, typename ContainerType>
class Stack{
typedef typename ContainerType::value_type underlying_value_type;
typedef char ERROR_different_value_type[
std::tr1::is_same<T, underlying_value_type>::value ? 1 : -1
]
ContainerType container;
// ...
};
Это работает, потому что если T
отличается от T
используемого контейнера, это будет typedef char ERROR_different_vale_type[-1]
, и массив отрицательного размера не может существовать, что вызывает ошибку компилятора. :) Теперь с C ++ 0x вы можете просто static_assert
, что:
#include <tr1/type_traits> // C++03
//#include <type_traits> // C++0x
template <typename T, typename ContainerType>
class Stack{
typedef typename ContainerType::value_type underlying_value_type;
static_assert(std::tr1::is_same<T, underlying_value_type>::value,
"Error: The type of the stack must be the same as the type of the container");
ContainerType container;
// ...
};
Для удобства теперь вы можете указать аргумент шаблона по умолчанию для общего случая:
template <typename T, typename ContainerType = std::vector<T>>
class Stack{
ContainerType container;
// ...
};
// usage:
Stack<int> s;
И в этот момент вы можете просто использовать std::stack
, который делает именно это (хотя он использует std::deque
в качестве базового типа). :)