提问人:Mat 提问时间:1/8/2010 最后编辑:Jan SchultkeMat 更新时间:9/23/2023 访问量:288800
“typename”和“class”模板参数有什么区别?
What is the difference between "typename" and "class" template parameters?
问:
对于模板,我看到了两个声明:
template < typename T >
template < class T >
有什么区别?
在下面的例子中,这些关键词到底是什么意思(摘自德语维基百科关于模板的文章)?
template < template < typename, typename > class Container, typename Type >
class Example
{
Container< Type, std::allocator < Type > > baz;
};
答:
- 没有区别
- 模板类型参数本身是具有两个类型参数的模板。
Container
评论
template<template<class U> class V> struct C {};
用于命名模板参数,并且是等效的。§14.1.2:typename
class
没有语义差异 在 class 和 typename 之间 template-参数。
typename
但是,在使用模板时,可以在另一个上下文中 - 向编译器提示您引用的是依赖类型。§14.6.2:
模板声明中使用的名称 或定义,这取决于 假设模板参数不 命名类型,除非适用的名称 查找查找类型名称或名称 由关键字 typename 限定。
例:
typename some_template<T>::some_type
没有编译器,通常无法判断您是否引用了某个类型。typename
评论
虽然没有技术上的区别,但我看到两者用来表示略有不同的东西。
对于应接受任何类型作为 T 的模板,包括内置(如数组)
template<typename T>
class Foo { ... }
对于仅适用于 T 是真实类的模板。
template<class T>
class Foo { ... }
但请记住,这纯粹是一些人使用的风格。标准不强制要求,编译器也不强制执行
评论
T t; int i = t.toInt();
int
T
class
class
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 >
指定模板模板时,必须如上所述使用关键字 - 在这种情况下它不能互换(注意:由于 C++17 在这种情况下允许使用这两个关键字)。class
typename
显式实例化模板时还必须使用:class
template class Foo<int>;
我敢肯定我错过了其他情况,但底线是:这两个关键字并不等价,这些是您需要使用其中一个的常见情况。
评论
template <typename T> typename Foo {};
std::vector<int>::value_type
不是一个依赖类型,你不需要那里 - 你只需要它,比如说一个类型依赖于模板参数typename
template<class T> struct C { typedef typename std::vector<T>::value_type type; };
param_t
foo<param_t>::some_type
GCC 5
开始,G++ 现在允许在模板模板参数中使用 typename。
这段代码来自 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 更清楚地表明后面的名称是类型名称。但是,在模板已经广泛使用之后,类型名被添加到 C++ 中;一些程序员继续专门使用类
使用 OR 没有区别;即它是C++程序员使用的约定。我自己更喜欢它,因为它更清楚地描述了它的用途;即定义具有特定类型的模板。<typename T>
<class T>
<typename T>
注意:有一个例外,在声明模板模板参数时,您必须使用(而不是):class
typename
template <template <typename> class T> class C { }; // valid!
template <template <typename> typename T> class C { }; // invalid!
在大多数情况下,您不会定义嵌套模板定义,因此任何一个定义都可以工作 - 只需在使用中保持一致即可。
评论