关于C++:对于模板参数使用”类”或”类型名”?

Use 'class' or 'typename' for template parameters?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
C++ difference of keywords ‘typename’ and ‘class’ in templates

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

1
template <class T> ...

或者你可以这样写:

1
template <typename T> ...

有没有一个比另一个更喜欢的理由?

我接受了最受欢迎(也最有趣)的答案,但真正的答案似乎是"不,没有什么好的理由比另一个更喜欢一个"。

  • 它们是等效的(除非下文另有说明)。
  • 有些人有理由总是使用typename
  • 有些人有理由总是使用class
  • 有些人有理由两者兼用。
  • 有些人不在乎他们用的是哪一种。

但是,注意,对于模板模板参数,需要使用class而不是typename。请参阅下面的用户142839的答案。(但这一特殊情况并非偏好问题,而是语言的要求。)(这也将随着c++17的变化而变化)


斯坦·利普曼在这里谈过这个。我觉得很有趣。

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


根据Scott Myers,有效的C++(第三ED)项目42(当然,这必须是最终的答案)-差异是"没有"。

建议在需要时使用"class",如果可能需要其他类型(int,char*随便什么),则T将始终是一个类,并使用"typename"。把它当作用法提示。


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

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

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

1
error: expected 'class' before 'Container'


我更喜欢使用typename,因为我不喜欢重载关键字(jeez——static在不同的上下文中有多少不同的含义?).


有区别,你应该选择class而不是typename。但是为什么呢?

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

1
2
template<template<class> typename MyTemplate, class Bar> class Foo { };    //  :(
template<template<class>    class MyTemplate, class Bar> class Foo { };    //  :)


纯粹的历史。引自Stan Lippman:

The reason for the two keywords is historical. In the original template specification, Stroustrup reused the existing class keyword to specify a type parameter rather than introduce a new keyword that might of course break existing programs. It wasn't that a new keyword wasn't considered -- just that it wasn't considered necessary given its potential disruption. And up until the ISO-C++ standard, this was the only way to declare a type parameter.

但是应该使用类型名而不是类!有关详细信息,请参见链接,但请考虑以下代码:

1
2
3
4
5
6
template <class T>
class Demonstration {
public:
void method() {
   T::A *aObj; // oops ...
};


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

1
2
3
4
5
6
7
8
9
10
11
12
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"的频率远比键入"typename"的频率高,因此发现键入起来容易得多。或者这可能是我写了太多OO代码的迹象。


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


据我所知,你用哪一个并不重要。在编译器看来,它们是等价的。用你喜欢的那种。我通常上课。


扩展darenw的评论。

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

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

template< char myc = '/' >

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

想想"含蓄"或其他人能理解。实际上,考虑到第三方软件/脚本可能试图使用代码/信息来猜测模板发生了什么(考虑到swig)。