对于模板,我看过两个声明:
template < typename T >
template < class T >
有什么区别?
这些关键字在以下示例中的确切含义是什么(取自德语维基百科关于模板的文章)?
template < template < typename, typename > class Container, typename Type >
class Example
{
Container< Type, std::allocator < Type > > baz;
};
答案 0 :(得分:351)
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 >
指定模板模板时,必须按上述方式使用class
关键字 - 在这种情况下 可与typename
互换(注意:由于C ++ 17在这种情况下允许两个关键字)。
在显式实例化模板时,您还必须使用class
:
template class Foo<int>;
我确信还有其他一些我错过的案例,但最重要的是:这两个关键字并不相同,而且这些是您需要使用其中一个的常见情况。
答案 1 :(得分:75)
对于命名模板参数,typename
和class
是等效的。 §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)
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 class C { }; // 有效!
template class C { }; // 无效!
在大多数情况下,您不会定义嵌套模板定义,因此任何一个定义都可以使用——只要在您的使用中保持一致...