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

Instantiate a template class <erroneous-expression>?

本文关键字:erroneous-expression gt lt 实例化      更新时间:2023-10-16

下面是我的代码:

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::allocatorstd::vector都是类模板,但Container不是类模板。它是类模板的模板参数。这就是为什么typename =T是允许的,而std::allocator这样的类模板是不允许的。