【问题标题】:Instantiate a template class <erroneous-expression>?实例化一个模板类<错误表达式>?
【发布时间】:2011-08-26 22:54:58
【问题描述】:

这是我的代码:

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>

但我想问一下,当您不使用模板类型参数时,我已经阅读过,那么您可以这样写:&lt;typename=default_type&gt;&lt;typename&gt;。此外,上述代码中的T 在模板模板参数Container 的参数列表中可见(即类型参数T 在其整个参数化子句中可见)。所以总而言之,我认为它应该可以工作。 但它没有并给出错误:

error: expression '<erroneous-expression> = <erroneous-expression>' is not a constant-expression
error: template argument 1 and 2 are invalid

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

【问题讨论】:

  • "erroneous-expression" 可能只是你的编译器被混淆了。

标签: c++ templates


【解决方案1】:

当一个模板参数本身就是一个模板时,除了定义模板模板参数的“模板签名”之外,它自己的模板参数在外部模板的上下文中不被使用或相关。因此,您不需要参数名称,因为它们不可用或不需要。你可以这么说:

template <typename T, template<typename, typename> class Container = std::vector>
class stack
{
  typedef Container<T, std::allocator<T> > CT;
  // ...
};

这里的template &lt;typename, typename&gt; 只是您期望的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

回答你的问题:你想在

中指定一个默认的type
 template <typename = T, typename = std::allocator<typename> > class Container
                                    ^^^^^^^^^^^^^^^^^^^^^^^^
                                            Error!!

但是std::allocator&lt;typename&gt; 不是类型——它甚至不是合法的语法。你可以有一个模板参数,它又是一个模板,即template &lt;typename&gt; = std::allocator,但它不会被std::vector 匹配,或者你有一个实际的类型:

template <typename = T, typename = std::allocator<T> > class Container
                                   ^^^^^^^^^^^^^^^^^
                                   OK, this is a type

【讨论】:

  • 您仍然没有回答为什么我的代码(第一个代码块的第一行)不起作用?
  • 第二个嵌套默认类型typename =std::allocator&lt;typename = T&gt; 不起作用,因为那不是类型,而是模板。你应该说的是typename =std::allocator&lt;T&gt;,因为那是一种类型。
  • 感谢Kerrek 提供了很好的解释 答案),顺便说一句,考虑您的编辑答案,因为我的行是 std::allocator
  • 没问题。不过,我刚刚修复了一个错误:您 can 确实具有模板参数的参数的默认类型,就像您在代码中所做的那样;默认类型并不像我最初声称的那样无用。事实上,当你说Container&lt;T&gt; 时,你依赖的是Container 中的默认类型。
【解决方案2】:

在类模板的parameter-list中,当你指定template模板参数时,template模板参数的模板参数没有被使用(其实他们不能使用)。因此,您甚至可以跳过提及他们的名字。

所以你应该做的是:

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&lt;typename = T&gt; 应该只是std::allocator&lt;T&gt;。也就是说,这应该有效:

template<typename T, template<typename =T,typename =std::allocator<T> >  class Container= std::vector>

在这里查看:http://ideone.com/eO8qT

但是,模板模板参数的这种默认类型甚至不被考虑。他们被忽略了。

现在您可能会问为什么std::allocator&lt;typename =T&gt; 不起作用。因为它的格式不正确。你认为std::vector&lt;typename =T&gt; 有意义吗?请注意std::allocatorstd::vector 都是类模板,但Container 不是类模板。它是一个类模板的模板模板参数。这就是为什么 typename =T 被允许用于此,而它不允许用于诸如 std::allocator 之类的类模板。

【讨论】:

  • 您仍然没有回答为什么我的代码(第一个代码块的第一行)不起作用?
  • 你的意思是“然后模板参数模板参数没有使用(实际上它们不能使用)”?
  • @Mr.阿努比斯:现在我解释了。你应该写简单的std::allocator&lt;T&gt;,而不是std::allocator&lt;typename = T&gt;
  • 你总是告诉我哪一行有问题并消除了错误。你没有一次告诉我为什么我不应该做这样的事情以及为什么会发生这种情况:(,看起来这里的很多点都没有帮助:(
  • @Mr.阿努比斯:我认为这就够了。但后来我意识到这对你来说还不够。无论如何,我添加了一个解释。
猜你喜欢
  • 2019-11-17
  • 2014-04-20
  • 1970-01-01
  • 1970-01-01
  • 2012-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多