为什么std :: stack不使用模板模板参数?
为什么std::stack
和std::queue
使用types模板参数而不是模板模板参数作为它们的底层容器types?
即为什么stack
声明如下:
template<typename T, typename Container = deque<T>> class stack;
但不是这样的:
template<typename T, template<typename> class Container = deque> class stack;
?
因为像std::vector
这样的容器通常具有多个模板参数 。 通过不关心它是一个模板,你可以使用每一种容器。
怎么会
template<class T, class Allocator = std::allocator<T>> class vector;
适合
template<typename> class Container
你会在你的stack
? (提示:它不!)你会需要特殊的情况下每个数字和types的模板参数(types与非types),你想支持,这是愚蠢的,因为这些通常不贡献任何比简单更多的信息
typename Container
请注意,为了得到例如std::vector
的实际模板参数,你可以使用typedefs std::vector::value_type
和std::vector::allocator_type
,这样就不需要在实际使用的地方显式使用这些typestypes(即stack
的Container
)。
使用模板模板参数会将可以用作底层容器的types限制为暴露相同模板签名的types。 只要支持期望的接口,这种forms允许任意types。
简而言之:因为使用模板模板参数比使用types参数更具限制性而没有提供任何优势。
*“限制”我的意思是,你可能需要一个更复杂的东西,以获得相同的结果,“简单”types的参数。
为什么没有优势?
你的std::stack
可能有这样的属性:
template <typename T, typename Container> struct stack { Container container; };
如果您通过模板模板参数replaceContainer
,为什么要获取?
template <typename T, template <typename...> class Container> struct stack { Container<T> container; };
你仅仅为T
( 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
也许你可以使用可变模板:
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...
使用types参数不存在这样的问题1 :
stack<int> stack<int, std::vector<int, MyAllocator<int>> stack<int, MyTemplate<int, MyParam1, MyParam2>> stack<foo, foo_container>
1还有其他一些不能与模板模板参数一起工作的情况,比如使用特定顺序接受混合types和非types参数的模板,即使使用可变参数模板,也可以创buildgenerics模板参数。
因为它不能编译 :
std::deque
不是types的
template <typename T> class std::deque
这是types的
template<class T, class Alloc> class std::deque
这当然是一个更普遍的问题:即使我们要为我们的stack
类模板提供Alloc
模板参数,这个类现在只能用于具有两个types模板参数的容器。 这是一个不合理的限制。