模板中关键字'typename'和'class'的区别?

时间:2010-01-07 21:59:41

标签: c++ templates keyword

对于模板,我看过两个声明:

template < typename T >
template < class T >

有什么区别?

这些关键字在以下示例中的确切含义是什么(取自德语维基百科关于模板的文章)?

template < template < typename, typename > class Container, typename Type >
class Example
{
     Container< Type, std::allocator < Type > > baz;
};

6 个答案:

答案 0 :(得分:351)

在指定模板的基本情况下,

typenameclass可以互换:

template<class T>
class Foo
{
};

template<typename T>
class Foo
{
};

是等价的。

话虽如此,但在typenameclass之间存在差异的特定情况。

第一个是依赖类型的情况。 typename用于在引用依赖于另一个模板参数的嵌套类型时声明,例如此示例中的typedef

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

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

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

指定模板模板时,必须按上述方式使用class关键字 - 在这种情况下 可与typename互换(注意:由于C ++ 17在这种情况下允许两个关键字)

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

template class Foo<int>;

我确信还有其他一些我错过的案例,但最重要的是:这两个关键字并不相同,而且这些是您需要使用其中一个的常见情况。

答案 1 :(得分:75)

对于命名模板参数,typenameclass是等效的。 §14.1.2:

  

没有语义差异   在一个类和类型名之间   模板参数。

typename但是在使用模板时可以在另一个上下文中使用 - 暗示您指的是依赖类型的编译器。 §14.6.2:

  

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

示例:

typename some_template<T>::some_type

如果没有typename,编译器通常无法判断您是否指的是类型。

答案 2 :(得分:18)

虽然没有技术差异,但我看到这两个用来表示略有不同的东西。

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

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

对于只能在T是真实类的情况下才能工作的模板。

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

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

答案 3 :(得分:6)

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

答案 4 :(得分:4)

这段片段来自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 ++中;一些程序员继续专门使用类

答案 5 :(得分:0)

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

注意:在声明模板模板参数时,有一个例外,您必须使用类(而不是类型名):

template