使用'class'或'typename'作为模板参数?

时间:2008-10-17 17:43:59

标签: c++ templates

  

可能重复:
  C++ difference of keywords ‘typename’ and ‘class’ in templates

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

template <class T> ...

或者可以写下这个:

template <typename T> ...

是否有充分的理由选择其中一个?


我接受了最受欢迎(也很有趣)的答案,但真正的答案似乎是“不,没有理由更喜欢一个而不是另一个。”

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

但请注意,对于模板模板参数,需要使用class代替typename。请参阅下面的user1428839's answer。 (但这个特殊情况不是偏好问题,而是语言的要求。)(这也会随着c++17而改变)

10 个答案:

答案 0 :(得分:383)

Stan Lippman谈到了here。我觉得这很有意思。

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

答案 1 :(得分:297)

根据Scott Myers的说法,Effective C ++(第3版)第42项(当然,这必须是最终答案) - 差异是“没有”。

建议是使用“class”如果预期T将永远是一个类,如果可能需要其他类型(int,char *,则为“typename”)。考虑一下使用提示。

答案 2 :(得分:143)

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

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

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

error: expected 'class' before 'Container'

答案 3 :(得分:47)

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

答案 4 :(得分:15)

的区别,您应该更喜欢classtypename

但为什么?

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

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

答案 5 :(得分: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'比'typename'更频繁,因此更容易输入。或者它可能是我写了太多OO代码的标志。

答案 6 :(得分:9)

纯粹的历史。 Quote from Stan Lippman

  

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

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

template <class T>
class Demonstration { 
public:
void method() {
   T::A *aObj; // oops ...
};

答案 7 :(得分:7)

根本不重要,但是类使它看起来像T只能是一个类,而它当然可以是任何类型。所以typename更准确。另一方面,大多数人使用类,因此通常更容易阅读。

答案 8 :(得分:1)

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

答案 9 :(得分:-3)

扩展DarenW的评论。

一旦不接受typename和class非常不同,它们的使用可能仍然有效。仅当class真的是类时才使用class,而当它是基本类型时使用typename,例如 char

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

  

模板&LT; char myc ='/'&gt;

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

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