602

可能重复:
模板中关键字“typename”和“class”的 C++ 差异

在 C++ 中定义函数模板或类模板时,可以这样写:

template <class T> ...

或者可以这样写:

template <typename T> ...

有充分的理由偏爱其中一个吗?


我接受了最受欢迎(和有趣)的答案,但真正的答案似乎是“不,没有充分的理由偏爱其中一个。”

  • 它们是等价的(除非如下所述)。
  • 有些人有理由总是使用typename.
  • 有些人有理由总是使用class.
  • 有些人有理由同时使用两者。
  • 有些人不在乎他们使用哪一个。

但是请注意,在 C++17 之前,对于模板模板参数,需要使用 ofclass代替typename。请参阅下面的 user1428839 的答案。(但这种特殊情况不是偏好问题,而是语言的要求。)

4

10 回答 10

433

Stan Lippman在这里谈到了这一点。我觉得这很有趣。

摘要: Stroustrup 最初用于class在模板中指定类型以避免引入新关键字。委员会中的一些人担心这种关键字的重载会导致混乱。后来,委员会引入了一个新的关键字typename来解决语法歧义,并决定让它也用于指定模板类型以减少混淆,但为了向后兼容,class保留其重载含义。

于 2008-10-17T17:47:57.013 回答
319

根据 Scott Myers,Effective C++(第 3 版)第 42 条(当然,它必须是最终答案)的说法——区别是“什么都没有”。

如果预期 T 将始终是一个类,建议使用“class”,如果可能预期其他类型(int、char* 等等),则使用“typename”。将其视为使用提示。

于 2008-10-17T17:52:13.447 回答
157

作为上述所有帖子的补充,在处理模板模板参数class,强制使用关键字(直到并包括 C++14) ,例如:

template <template <typename, typename> class Container, typename Type>
class MyContainer: public Container<Type, std::allocator<Type>>
{ /*...*/ };

在此示例中,typename Container会生成编译器错误,如下所示:

error: expected 'class' before 'Container'
于 2012-07-03T12:57:07.270 回答
50

我更喜欢使用 typename 因为我不喜欢重载关键字(天哪 -static对于各种不同的上下文有多少不同的含义?)。

于 2008-10-17T17:52:29.470 回答
17

区别,您应该更class喜欢typename.

但为什么?

typename对于模板模板参数是非法的,因此为了保持一致,您应该使用class

template<template<class> typename MyTemplate, class Bar> class Foo { };    //  :(
template<template<class>    class MyTemplate, class Bar> class Foo { };    //  :)
于 2012-07-23T15:50:24.110 回答
9

作为对Mike B的回应,我更喜欢使用 'class',因为在模板中,'typename' 具有重载的含义,但 'class' 没有。以这个检查过的整数类型为例:

template <class IntegerType>
class smart_integer {
public: 
    typedef integer_traits<Integer> traits;
    IntegerType operator+=(IntegerType value){
        typedef typename traits::larger_integer_t larger_t;
        larger_t interm = larger_t(myValue) + larger_t(value); 
        if(interm > traits::max() || interm < traits::min())
            throw overflow();
        myValue = IntegerType(interm);
    }
}

larger_integer_t是一个从属名称,因此它需要在它之前加上“typename”,以便解析器可以识别出它larger_integer_t是一种类型。 另一方面, class没有这种重载的含义。

那……或者我只是内心懒惰。我键入 'class' 的频率远高于 'typename',因此发现它更容易键入。或者这可能表明我写了太多的 OO 代码。

于 2008-10-17T20:21:02.867 回答
9

只是纯粹的历史。引用斯坦·李普曼的话

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

但是应该使用typename而不是class!有关更多信息,请参阅链接,但请考虑以下代码:

template <class T>
class Demonstration { 
public:
void method() {
   T::A *aObj; // oops ...
};
于 2010-04-01T08:03:22.097 回答
8

一点都不重要,但是 class 使它看起来 T 只能是一个类,而它当然可以是任何类型。所以 typename 更准确。另一方面,大多数人使用类,所以一般来说可能更容易阅读。

于 2008-10-17T19:26:10.560 回答
1

据我所知,使用哪一个并不重要。它们在编译器眼中是等价的。使用您喜欢的任何一个。我通常使用类。

于 2008-10-17T17:47:35.953 回答
-6

扩展DarenW的评论。

一旦 typename 和 class 不被认为是非常不同的,那么严格使用它们可能仍然有效。只有当它确实是一个类时才使用 class,当它是基本类型时使用 typename,例如char

这些类型确实也被接受而不是typename

模板< char myc = '/' >

在这种情况下,它甚至优于 typename 或 class。

想想其他人的“暗示”或可理解性。并且实际上考虑到第 3 方软件/脚本可能会尝试使用代码/信息来猜测模板发生了什么(考虑 swig)。

于 2009-10-28T12:37:56.870 回答