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

时间:2016-08-02 13:20:14

标签: c++ templates

为什么std::stackstd::queue使用类型模板参数而不是模板模板参数作为基础容器类型?

即。为什么stack声明如下:

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

但不是这样的:

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

4 个答案:

答案 0 :(得分:38)

因为通常是std::vector have more than one template argument之类的容器。通过不关心它是一个模板,你允许使用各种容器。

怎么会

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

适合

template<typename> class Container

就像你在stack中一样? (提示:它没有!)你需要特殊情况来处理你想要支持的每个数字和类型的模板参数(类型与非类型),这很愚蠢,因为这些通常不会贡献任何比简单的更多信息

typename Container

请注意,要获取实际的模板参数,例如一个std::vector,你有typedef std::vector::value_typestd::vector::allocator_type,无需在实际使用类型的地方明确提供这些类型(即Container {{1} }})。

答案 1 :(得分:18)

简而言之:因为使用模板模板参数比使用类型参数更具限制性*而没有任何优势。

* 限制性我的意思是你可能需要更复杂的东西才能获得与&#34;简单&#34;相同的结果。类型参数。

为什么没有优势?

你的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 TContainer<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...

使用类型参数时,没有这样的问题 1

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

1 还有其他情况不适用于模板模板参数,例如使用模板接受特定订单中的类型和非类型参数的混合,您可以为其创建通用模板模板参数,甚至使用可变参数模板。

答案 2 :(得分:18)

使用模板模板参数会将可用作底层容器的类型限制为公开相同模板签名的类型。只要这些表单支持预期的接口,它就允许任意类型。

答案 3 :(得分:13)

Because it doesn’t compile

host/wps/um/secure/users/profiles?searchAttributes=createTimestamp=yyyy-MM-dd'T'HH:mm:ss'Z' 不属于

类型
std::deque

类型

template <typename T> class std::deque

这当然是一个更普遍的问题:即使我们要向template<class T, class Alloc> class std::deque 类模板提供Alloc模板参数,该类现在只能使用具有两个类型模板的容器参数。这是一个不合理的限制。