实例化模板类<erroneous-expression>?</erroneous-expression>

时间:2011-08-26 14:22:17

标签: c++ templates

这是我的代码:

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

所以任何人都可以解释为什么我看到这些错误,什么是错误表达?

2 个答案:

答案 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::allocatorstd::vector都是类模板,但Container不是类模板。它是类模板的模板模板参数。这就是原因,typename =T是允许的,而std::allocator等类模板则不允许这样做。