c++ - 模板中关键字“typename”和“class”的区别?


对于模板,我已经看到这两个声明:

template < typename T >
template < class T >

有什么不同?

在下面的例子中,这些关键字究竟意味着什么(摘自德国维基百科有关模板的文章)?

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


Answers



在指定模板的基本情况下, 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>;

我相信还有其他一些我错过的例子,但底线是:这两个关键字是不相同的,这些是一些常见的情况下,你需要使用一个或另一个。




为了命名模板参数, typenameclass是等价的。 §14.1.2:

模板参数中的类和类型名称之间没有语义上的区别。

然而,在使用模板的时候,在另一个上下文中可以使用typename来提示编译器引用了依赖类型。 §14.6.2:

除非可用的名称查找找到类型名称或名称由关键字typename限定,否则假定在模板声明或定义中使用的名称(取决于模板参数)不会命名类型。

例:

typename some_template<T>::some_type

如果没有typename那么编译器通常不能说明你是否指向一个类型。




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

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

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

对于仅在T是真实类的地方使用的模板。

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

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




  1. 没有不同
  2. 模板类型参数Container本身是一个具有两个类型参数的模板。



这段代码是从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 ++中。 一些程序员继续单独使用类