我真的很困惑模板。 如果我有一个模板类并将其作为参数传递给函数,请考虑以下内容:
template <class T> class Class
{
};
所以我想创建一个以Class作为参数的函数,那么为什么以下这些还不够:
void func(Class<T> obj)
{
}
我必须这样做:
template <class T> void func(Class<T> obj)
{
}
另外,我说2个模板类的2个参数,请考虑以下内容:
template <class T> class ClassA
{
};
template <class T> class ClassB
{
};
我有一个函数,它接受ClassA和ClassB类型的2个参数,写作之间的区别是什么:
template <class T> void func(ClassA<T> obj1, ClassB<T> obj2)
{
}
到
template <class T, class ClassB> void func(ClassA<T> obj1, ClassB obj2)
{
}
因为两者都有效。
答案 0 :(得分:3)
不要对 template-parameter-list 中class
语法中的class ClassB
关键字感到困惑。也就是说,class
关键字并不表示实际的类(甚至没有给定名称的类),而是一个类型的名称,可以推导出来或在 template-argument-list 中指定。或者,(我更喜欢),您可以使用typename
关键字,更好地表达其含义:
那是:
template <class T, class ClassB> void func(ClassA<T> obj1, ClassB obj2)
等于:
template <typename T, typename ClassB> void func(ClassA<T> obj1, ClassB obj2)
ClassB
范围内的func
名称会影响class ClassB
声明。在函数的范围内,这是在 template-argument-list 中推导或指定的类型的名称。也就是说,它几乎可以是任何东西:
func(ClassA<int>{}, 123); // ClassB is now deduced to be int
func(ClassA<int>{}, 3.14); // ClassB is now deduced to be double
func(ClassA<int>{}, 'A'); // ClassB is now deduced to be char
func<int, long long>(ClassA<int>{}, 5); // ClassB is specified to be long long
一个说明阴影的例子:
template <class T, class ClassB> void func(ClassA<T> obj1, ClassB obj2)
{
ClassB a; // a has the deduced or specified type
::ClassB<int> b; // b has the true ClassB<int> type
}
最后,上述声明与下面的声明之间的区别:
template <class T> void func(ClassA<T> obj1, ClassB<T> obj2)
在后一种情况下,func
接受具有相同类型参数的ClassA
实例和ClassB
实例,而第一个声明,如所述,可以匹配任何类型第二个。
换句话说,在第一个示例中,第一个参数类型的模板参数推导机制被限制为仅推导出T
声明中的ClassA<T>
类型,并且不以任何方式限制推导出第二个参数的类型。
答案 1 :(得分:1)
类模板不是类,函数模板也不是函数,它们只是制作它们的模板。
因此,难怪你不能使用需要相应功能的模板。
模板参数的名称与其范围之外的函数参数的名称具有相同的重要性:
没有任何。在它们的范围内,它们自然会影响外部范围的名称。
因此,令牌T
可能不表示您尝试声明(并且另外定义)您的功能的任何内容。
模板中的ClassB
作为template-argument-name,表示teplate-argument,而不是某些可能恰好存在的外部范围类。