使用“class”或“typename”作为模板参数?
可能重复:
模板中的关键字'typename'和'class'的C ++差异
在C ++中定义函数模板或类模板时,可以这样写:
template <class T> ...
或者可以这样写:
template <typename T> ...
有一个比另一个更好的理由吗?
我接受了最stream行(也是最有意思)的答案,但真正的答案似乎是“不,没有理由相互优先select”。
- 它们是相同的(除非如下所述)。
- 有些人有理由总是使用
typename
。 - 有些人有理由一直使用
class
。 - 有些人有理由同时使用。
- 有些人不在乎他们使用哪一个。
但是,请注意,在模板模板参数的情况下,需要使用class
而不是typename
。 请参阅下面的user1428839的答案 。 (但这个特殊情况并不是偏好问题,而是语言的一个要求。)(这也会随着c++17
变化而变化)
斯坦·李普曼在这里谈到了这一点 。 我认为这很有趣。
总结 :Stroustrup最初使用class
来指定模板中的types,以避免引入新的关键字。 委员会中的一些人担心这个关键字的超载导致了混淆。 之后,委员会引入了一个新的关键字typename
来解决语义上的歧义,并决定让它用来指定模板types以减less混淆,但为了向后兼容, class
保持其超载的含义。
根据斯科特·迈尔斯(Scott Myers)的说法,Effective C ++(第3版)第42项(当然必须是最终的答案) – 区别是“没有”。
build议是使用“类”如果预期T将永远是一个类,与“types名”如果其他types(INT,CHAR *无论)可能是预期的。 考虑一下使用提示。
作为上述所有post的补充,在处理模板模板参数时强制使用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'
请参阅http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4051.html,了解在C ++ 14中模板模板中是否接受typename。
我更喜欢使用typename,因为我不是超载关键字的粉丝(jeez – 对于各种不同的上下文, static
有多less不同的含义?)。
有一个区别,你应该喜欢class
到typename
。
但为什么?
typename
对于模板模板参数是非法的,所以为了保持一致,你应该使用class
:
template<template<class> typename MyTemplate, class Bar> class Foo { }; // :( template<template<class> class MyTemplate, class Bar> class Foo { }; // :)
为了回应Mike B ,我更喜欢使用'class',因为在模板中,'typename'具有重载意义,但'class'不是。 以这个检查整数types的例子:
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
是一个独立的名称,所以它需要在其larger_integer_t
“typename”,以便parsing器可以识别出larger_integer_t
是一个types。 另一方面,这个类没有这样的重载意义。
那…或者我只是懒惰的内心。 我比'typename'更经常地键入'class',因此更容易input。 或者这可能是我写了太多面向对象代码的标志。
根本不重要,但是class级看起来像T只能是一个class级,当然可以是任何types的class级。 所以typename更准确。 另一方面,大多数人使用类,所以一般来说可能更容易阅读。
只是纯粹的历史。 引自Stan Lippman :
这两个关键词的原因是历史的。 在原始模板规范中,Stroustrup重用了现有的类关键字来指定一个types参数,而不是引入一个新的关键字,当然这个关键字可能会破坏现有的程序。 这并不是说没有考虑到新的关键字 – 只是考虑到它的潜在破坏,它不被认为是必要的。 直到ISO-C ++标准,这是声明types参数的唯一方法。
但是应该使用typename而不是class ! 查看链接了解更多信息,但请考虑以下代码:
template <class T> class Demonstration { public: void method() { T::A *aObj; // oops ... };
据我所知,你使用哪一个并不重要。 在编译器的眼中,它们是相同的。 使用你喜欢的任何一个。 我通常使用类。
扩展DarenW的评论。
一旦typename和class不被接受是非常不同的,严格使用它可能仍然是有效的。 使用类只有当它是一个基本的types,如char 。
这些types确实也被接受,而不是typename
模板< char myc ='/'>
在这种情况下甚至会优于typename或class。
想一下“hintfullness”或其他人的可理解性。 并且实际上考虑第三方软件/脚本可能会尝试使用代码/信息来猜测模板发生了什么(考虑swig)。