【问题标题】:Why are structs not allowed in template definitions?为什么模板定义中不允许使用结构?
【发布时间】:2010-03-25 23:18:34
【问题描述】:

以下代码产生错误error: ‘struct Foo’ is not a valid type for a template constant parameter

template <struct Foo>
struct Bar {

};

为什么会这样?

template <class Foo>
struct Bar {

};

工作得很好,甚至可以接受一个结构作为参数。

【问题讨论】:

  • 因为 C++ 语言将其定义为这样,classtypenametypename 从我的角度来看更能描述正在发生的事情,否则请尝试用 @987654327 替换它@ 出于某种未知原因...template &lt;typename Foo&gt; 表示有一个type,我将调用Foo,它将替换为编译期间使用的实际类型...

标签: c++ templates


【解决方案1】:

这只是语法规则的产物——语法只是让您使用classtypename 关键字来指示类型模板参数。否则参数必须是“非类型”模板参数(基本上是整数、指针或引用类型)。

我想 Stroustrup(以及他可能接受过输入的任何其他人)认为没有必要包含 struct 作为关键字来指示类型模板参数,因为不需要向后兼容 C。

事实上,我的回忆(我回家后必须读一本书)是,当添加typename 以指示模板类型参数时,Stroustrup 会喜欢为此目的使用 class 关键字(因为它令人困惑),但是依赖它的代码太多。


编辑:

事实证明这个故事更像(来自blog entry by Stan Lippman):

这两个关键字的原因是 历史的。在原始模板中 规范,Stroustrup 重用了 现有的类关键字来指定一个 类型参数而不是引入 当然可能会破坏的新关键字 现有程序。这不是一个 没有考虑新关键字——只是 认为没有必要 鉴于其潜在的破坏性。向上 直到 ISO-C++ 标准,这是 声明类型的唯一方法 参数。

重复使用现有的关键字似乎 总是种下混乱。我们发现的是 初学者[想知道] 是否使用类 约束或限制类型 用户可以指定的参数 类类型,而不是,比如说, 内置或指针类型。所以,有 是某种感觉,没有 引入了一个新的关键字是 错误。

在标准化过程中,某些 在一个内部发现了构造 解析为的模板定义 表达虽然他们是故意的 表示声明

...

委员会决定采用新的 关键字只是获得的门票 编译器摆脱了它不幸的痴迷 用表情。新关键字是 自描述类型名。

...

由于关键字在工资单上, 哎呀,为什么不解决造成的混乱 由原来的决定重用 类关键字。当然,鉴于 大量现有代码和 书籍、文章、演讲和 使用 class 关键字的帖子,他们 选择也保留对此的支持 关键字的使用也是如此。所以那是 为什么你都有。

【讨论】:

  • 从我记事起我就一直在使用template &lt;typename ...&gt;,我相信class 部分让人们感到困惑,认为它是实际的class,并想在其中粘贴struct奇怪的原因...
  • 至少在他的 C++0x FAQ (www2.research.att.com/~bs/C++0xFAQ.html) 中,Stroustrup 似乎以完全任意的方式使用typenameclass。可能没有办法避免“混乱”,因为迟早你会遇到使用 class 的代码(这只是更少输入通常冗长的模板代码,IMO),你必须知道没有还是有区别的。
【解决方案2】:

简短的回答是:template &lt;class Foo&gt; 甚至接受 uniondouble - 尽管如此,两者都不允许,而不是 class。但是,typename 是。这就是定义语法的方式。

一个稍微长一点的答案:当 C++ 模板“发明”时,在那个地方需要一个关键字,说明下一个标识符将是一个类型名称。决定重新使用现有的class 关键字。这有点令人困惑,但人们普遍不愿意引入更多关键字,因为它们总是会破坏一些现有的代码,这些代码在它不是关键字时将其用作标识符。

后来,typename 由于其他原因成为关键字,并且由于它更合适,现在可以在那个地方使用它:template &lt;typename Foo&gt;。然而,有数十亿行代码在那个地方使用class,它必须为此目的保持有效。所以现在两者都被允许了。

在 C++ 中很常见,这为在那个地方使用什么关键字创建了几个阵营。有些人坚持使用class,因为他们已经使用它十多年了。其他人更喜欢typename,因为它更合适。当Foo 预期为class 类型(成员被访问)时,有些人使用class,而在也可以使用内置函数时使用typename

【讨论】:

    【解决方案3】:

    您可以使用结构实例化模板;但是,声明模板类型的语法只允许关键字“class”或“typename”出现在您尝试使用关键字“struct”的地方。

    我应该补充一点,如果您想基于编译时常量或基于具有外部链接的对象来实例化模板,您还可以使用特定类型(例如 int)......但这有点旁白。

    【讨论】:

      【解决方案4】:

      因为模板参数的关键字是classtypename。这并不将 Foo 参数限制为一个类 - 它可以是任何类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-14
        • 2018-08-18
        • 2019-05-04
        • 2014-01-11
        • 1970-01-01
        • 1970-01-01
        • 2013-09-05
        • 1970-01-01
        相关资源
        最近更新 更多