我了解到可以使用模板以下列方式创建数据结构:
template<typename T>
struct X {
T weight;
int age;
};
这些功能也可以通过以下方式使用模板:
template <class T>
T func_name(int age, T human) {
something_here;
}
其中一个不同之处在于,在第一种情况下,我们使用typename
,而在第二种情况下,我们使用class
。
我找到了包含以下内容的代码:
template<typename S, typename T>
bool is_null(const row<T>& r)
所以,我无法理解的是为什么我们将typename
(而不是class
)与函数结合使用。我们不应该使用class
吗?
答案 0 :(得分:3)
在此上下文中,关键字typename
与关键字class
之间没有技术差异。这只是一种风格问题。如果前两个代码示例以template<class T> struct X
和template <typename T> T func_name(int age, T human)
开头,则它们的含义不会改变一位。 (我倾向于使用class
,当我的意思是暗示模板参数应该是一个类,而不是像int
那样。)
答案 1 :(得分:0)
首次引入template
时,它只允许现有关键字class
作为指示符“这是模板参数”。由于当模板参数实际上不是类(函数指针,整数类型或其他“非类”类型)时,这变得相当愚蠢,因此引入typename
以使其更清楚template<typename T> struct something { T x; };
1}}允许something<int> a;
以及something<name_of_class> a;
。
对于所有意图和目的,class
和typename
在模板参数的情况下是可以互换的,这只是你选择做的风格问题[大多数人可能更喜欢你坚持一,不要混合两者 - 或者,当类型为“是”类时,可能使用class
,而当它可以是“任何”类型时,可以使用typename
。
答案 2 :(得分:0)
在模板参数定义的上下文中,关键字typename
和class
是同义词。
几乎每个人都有一个他们倾向于坚持的约定。我个人更喜欢在这里始终使用class
并保留typename
关键字以供其他用途。
typename
的另一个用途是消除模板定义或声明中的依赖类型的歧义。
以下是wikipedia的示例:
template <typename T>
void foo(const T& t)
{
// declares a pointer to an object of type T::bar
T::bar * p;
}
struct StructWithBarAsType {
typedef int bar;
};
int main() {
StructWithBarAsType x;
foo(x);
}
如果你仔细观察,你会注意到T::bar * p;
行,bar
依赖于模板参数T
,这对编译器来说是不明确的,因为bar
可以是取决于用于实例化模板的类型T
的上下文的类型或值。默认设置是将bar
视为一个值,因此其含义是将T::bar
乘以p
,这不是我们想要的。
解决方案是使用typename
关键字限定依赖类型。
typename T::bar * p;
这会警告编译器我们打算将bar
视为一种类型。
答案 3 :(得分:0)
只有一个位置不同(声明模板参数时),即使用模板模板时。
以下是定义明确的C ++
template <template <typename> class TT> struct example_one {};
虽然不是这样:
template <template <typename> typename TT> struct example_two {};
由于您似乎刚刚开始使用C ++ /模板,这个角落的情况不会涉及到你一段时间:-)除了上面的类模板,函数模板,它没关系:typename和班级是同义词。