为什么std :: stack不使用模板模板参数?

为什么std::stackstd::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_typestd::vector::allocator_type ,这样就不需要在实际使用的地方显式使用这些typestypes(即stackContainer )。

使用模板模板参数会将可以用作底层容器的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; }; 

你仅仅为TContainer<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模板参数的容器。 这是一个不合理的限制。