“typename”和“class”模板参数有什么区别?

问题描述 投票:0回答:6

对于模板,我已经看到了两种声明:

template < typename T >
template < class T >

有什么区别?

在下面的示例中这些关键字到底意味着什么(取自德语维基百科关于模板的文章)?

template < template < typename, typename > class Container, typename Type >
class Example
{
     Container< Type, std::allocator < Type > > baz;
};
c++ templates keyword
6个回答
598
投票
在指定模板的基本情况下,

typename
class
是可以互换的:

template<class T>
class Foo
{
};

template<typename T>
class Foo
{
};

是等价的。

话虽如此,在某些特定情况下,

typename
class
之间存在差异。

第一个是依赖类型的情况。

typename
用于在引用依赖于另一个模板参数的嵌套类型时进行声明,例如本示例中的
typedef

template<typename param_t>
class Foo
{
    typedef typename param_t::baz sub_t;
};

您在问题中实际显示的第二个,尽管您可能没有意识到:

template < template < typename, typename > class Container, typename Type >

指定 template 模板时,必须按上述方式使用

class
关键字——在这种情况下,它不可与 typename
 互换 
(注意:自 C++17 起,在这种情况下这两个关键字都是允许的) ).

显式实例化模板时,您还必须使用

class

template class Foo<int>;

我确信我错过了其他情况,但底线是:这两个关键字并不等效,这些是您需要使用其中之一的常见情况。


127
投票
对于命名模板参数,

typename

class
是等效的。 §14.1.2:

没有语义差异 在 a 中的类和类型名之间 模板参数。

然而,当使用模板时,

typename

在另一个上下文中是可能的——暗示编译器您正在引用依赖类型。 §14.6.2:

模板声明中使用的名称 或定义,这取决于 假设模板参数不 命名类型,除非适用的名称 Lookup 查找类型名称或名称 由关键字 typename 限定。

示例:

typename some_template<T>::some_type

如果没有

typename

,编译器一般无法判断您是否引用了类型。


37
投票
虽然没有技术上的差异,但我发现这两者用来表示略有不同的事物。

对于应该接受任何类型作为 T 的模板,包括内置类型(例如数组)

template<typename T> class Foo { ... }

对于仅在 T 是真实类的情况下才有效的模板。

template<class T> class Foo { ... }

但请记住,这纯粹是一些人使用的一种风格。不受标准强制或由编译器强制执行


11
投票
    没有区别
  1. 模板类型参数
  2. Container
    本身就是一个具有两个类型参数的模板。
    

9
投票
使用

<typename T>

<class T>
 没有区别;即它是 C++ 程序员使用的约定。我自己更喜欢
<typename T>
,因为它更清楚地描述了它的用途;即定义具有特定类型的模板。

注意:有一个例外,在声明模板模板参数时,您必须使用

class

(而不是 
typename
):

template <template <typename> class T> class C { }; // valid! template <template <typename> typename T> class C { }; // invalid!
在大多数情况下,您不会定义嵌套模板定义,因此任一定义都可以工作——只需在使用中保持一致即可。


7
投票
这段代码摘自《c++ 入门书》。虽然我确信这是错误的。

每个类型参数前面必须带有关键字 class 或 typename:

// error: must precede U with either typename or class template <typename T, U> T calc(const T&, const U&);

这些关键字具有相同的含义,可以在模板参数列表中互换使用。模板参数列表可以使用这两个关键字:

// ok: no distinction between typename and class in a template parameter list template <typename T, class U> calc (const T&, const U&);

使用关键字 typename 而不是 class 来指定模板类型参数似乎更直观。毕竟,我们可以使用内置(非类)类型作为模板类型参数。而且,typename更清楚地表明后面的名称是类型名称。然而,在模板已经广泛使用之后,typename 才被添加到 C++ 中;一些程序员继续专门使用类

© www.soinside.com 2019 - 2024. All rights reserved.