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

Kri*_*son 572 c++ templates

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

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

template <class T> ...
Run Code Online (Sandbox Code Playgroud)

或者可以这样写:

template <typename T> ...
Run Code Online (Sandbox Code Playgroud)

是否有充分理由偏好一个而不是另一个?


我接受了最受欢迎(也很有趣)的答案,但真正的答案似乎是"不,没有理由偏爱另一个."

  • 它们是等价的(除非如下所述).
  • 有些人有理由一直使用typename.
  • 有些人有理由一直使用class.
  • 有些人有理由同时使用这两种方法.
  • 有些人并不关心他们使用哪一个.

但是,请注意,在模板模板参数的情况下,需要使用class而不是typename.请参阅下面的user1428839的答案.(但这个特殊情况不是偏好问题,而是语言的要求.)(这也会改变typename)

its*_*att 393

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

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

  • 并且不要忘记阅读评论是否有充分理由使用"class"而不是"typename". (5认同)
  • 复兴!老实说,我没有发现那篇文章特别清楚.在`T :: A*obj;`这个语言,据我所知,应该将语句解析为声明,因为声明规则:任何看起来像声明的东西,即使它含糊不清,也应该解决进入声明[0].我也没有发现Bjarne Stroustrup清楚这一点.[0] C++编程语言3e,Stroustrup,附录C.13.5,p.856-858 (2认同)

Dar*_*enW 303

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

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

  • 我喜欢提示因素的概念.我想我会开始使用它. (53认同)
  • 但是现在我们有了static_assert(std :: is_class <T> :: value,"T必须是一个类"); (10认同)
  • "C++模板完整指南"David Vandevoorde Nicolai M. Josuttis.2.1.1 (2认同)
  • 它也会长毛。/sf/answers/3248108391/ (2认同)

Jor*_*eit 146

作为除了所有上述职位,使用的class关键字被迫(直至并包括C++ 14),当处理模板的模板的参数,例如:

template <template <typename, typename> class Container, typename Type>
class MyContainer: public Container<Type, std::allocator<Type>>
{ /*...*/ };
Run Code Online (Sandbox Code Playgroud)

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

error: expected 'class' before 'Container'
Run Code Online (Sandbox Code Playgroud)

  • 看起来Clang 3.5和Visual Studio 2015现在支持模板模板参数中的N4051 typename. (4认同)
  • 至少目前,这是非常重要的,使得这个答案比接受的和第二高的答案更好. (2认同)

Mic*_*urr 47

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

  • 当然,typename也是重载的.... (39认同)
  • 没错,但它似乎不那么令人困惑地重载 - "typename"的其他用途令人困惑,不是因为过载和需要它的情况相当混乱.其他关键字重载(`class`或`static`)似乎是混乱的积极参与者. (8认同)
  • 我必须同意在这里使用`typename` - 使用类似乎过度使用了这个关键字,特别是在`template <class X> class Y {...` (5认同)
  • 就个人而言,如果它使用`typename`作为模板参数,我发现更容易浏览代码.如果我只是浏览,寻找类定义或声明,每次看到`class`时我都要仔细看看.与此同时,每当我看到`typename`时,我都会自动地想,"哦,这可能是一个模板声明,也可能是那些不稳定的情况之一." 相反,在浏览模板时,"class"可能会或可能不会指示一个,但是你知道`typename`只能在模板正在进行时使用. (3认同)

Meh*_*dad 15

这里一个区别,你应该更喜欢classtypename.

但为什么?

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

template<template<class> typename MyTemplate, class Bar> class Foo { };    //  :(
template<template<class>    class MyTemplate, class Bar> class Foo { };    //  :)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这种不一致性将由C++ 1z修复. (23认同)
  • C++ 0x,它变成了C++ 1x,是C++ 11.C++ 1y是C++ 14,当前版本.C++ 1z很可能是C++ 17,假设它不会在十年后期滑落. (6认同)

Aar*_*ron 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

larger_integer_t是一个从属名称,因此它需要'typename'在它之前,以便解析器可以识别这larger_integer_t是一个类型. 另一方面,阶级没有这样的超载意义.

那......或者我只是在懒惰.我输入'class'比'typename'更频繁,因此更容易输入.或者它可能是我写了太多OO代码的标志.

  • 我不认为这是超载.在这两种情况下,typename都是相同的:表示它后跟一个类型而不是一个变量. (9认同)
  • 但是"typedef"后面总是有一个类型,为什么这里需要"typename"?我可以理解它需要像`typename qwert :: yuiop*asdfg;`,如果有必要告诉解析器它是一个指针声明而不是乘法表达式.但是在typedef中没有这种模糊性. (4认同)

小智 9

只是纯粹的历史.来自Stan Lippman的报价:

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

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

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


Fre*_*man 7

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