这是我的代码:
template<typename T, template<typename = T,typename =std::allocator<typename = T> > class Container= std::vector>
class stack
{
public:
Container<T> cont;
stack()
{
}
};
如果我将第一行代码替换为下面的代码,那么它可以工作:
template<typename T, template<typename elem= T,typename =std::allocator<elem> > class Container= std::vector>
但我想问一下,当你不使用模板类型参数时,我已经阅读过,那么你可以写下:<typename=default_type>
或<typename>
。上面代码中的T
在模板模板参数Container
的参数列表中也可见(即类型参数T
在其整个参数化子句中可见)。总而言之,我认为它应该有效。
但它没有并给出错误:
error: expression '<erroneous-expression> = <erroneous-expression>' is not a constant-expression
error: template argument 1 and 2 are invalid
所以任何人都可以解释为什么我看到这些错误,什么是错误表达?
答案 0 :(得分:1)
当模板参数本身是模板时,除了定义template-template参数的“模板签名”之外,其外部模板的上下文中不使用或不相关其自己的模板参数。因此,您不需要任何参数名称,因为它们不可用或不必要。你可以这么说:
template <typename T, template<typename, typename> class Container = std::vector>
class stack
{
typedef Container<T, std::allocator<T> > CT;
// ...
};
此处template <typename, typename>
只是您期望的Container
模板类的模板签名。
在C ++ 11中,您可以通过使用可变参数模板做得更好并允许更多通用容器:
template <typename T, template<typename...> class Container = std::vector> class stack;
[完整性:]在模板参数的参数列表中设置默认类型也有效,这意味着您可以稍后省略这些类型(正如您已经做到的那样):
template<typename = T, typename = std::allocator<T> > class Container
---> now we can say:
Container<T> x; // use second default argument
Container<> y; // use both default arguments
要回答您的问题:您想在
中指定默认的类型 template <typename = T, typename = std::allocator<typename> > class Container
^^^^^^^^^^^^^^^^^^^^^^^^
Error!!
但是std::allocator<typename>
不是一种类型 - 它甚至不是合法的语法。你可以有一个模板参数,它再一次是一个模板,即template <typename> = std::allocator
,但不会被std::vector
匹配,或者你有一个实际的类型:
template <typename = T, typename = std::allocator<T> > class Container
^^^^^^^^^^^^^^^^^
OK, this is a type
答案 1 :(得分:0)
在类模板的参数列表中,指定模板模板参数时,不使用模板模板参数的模板参数(实际上,它们是无法使用)。因此,您可以跳过提及他们的名字。
所以你应该做的是:
template<typename T, template<class,class> class Container= std::vector>
class stack
{
Container<T, std::allocator<T> > cont;
};
也就是说,模板模板参数所需要的只是参数的数量,以及它们的参数:类型或值的信息。
您也可以写这个以获得更好的可读性:
template<typename T, template<class U,class Allocator> class Container= std::vector>
class stack
{
Container<T, std::allocator<T> > cont;
};
至于为什么你的第一个代码无效,因为std::allocator<typename = T>
应该只是std::allocator<T>
。也就是说,这应该有效:
template<typename T, template<typename =T,typename =std::allocator<T> > class Container= std::vector>
请在此处查看:http://ideone.com/eO8qT
但是,甚至没有考虑模板模板参数的默认类型。他们被忽略了。
现在您可能会问为什么std::allocator<typename =T>
不起作用。因为其形象不对称。你觉得std::vector<typename =T>
有道理吗?请注意,std::allocator
和std::vector
都是类模板,但Container
不是类模板。它是类模板的模板模板参数。这就是原因,typename =T
是允许的,而std::allocator
等类模板则不允许这样做。