实例化模板类<erroneous-expression>?
Instantiate a template class <erroneous-expression>?
下面是我的代码:
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
所以谁能解释为什么我看到这些错误,什么是错误的表达?
当模板参数本身是一个模板时,它自己的模板参数在外部模板的上下文中不被使用或不相关,除了定义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
在类模板的参数列表中,当指定模板模板参数时,则不使用模板模板参数的模板参数(实际上,它们不能使用)。因此,你甚至可以不提他们的名字。
那么你应该做的是:
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
这样的类模板是不允许的。