0

我真的对模板感到困惑。如果我有一个模板类并将其作为参数传递给函数,请考虑以下内容:

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
{

};

我有一个函数,它接受 2 个 ClassA 和 ClassB 类型的参数,写作之间有什么区别:

template <class T> void func(ClassA<T> obj1, ClassB<T> obj2)
{

}

template <class T, class ClassB> void func(ClassA<T> obj1, ClassB obj2)
{

}

因为两者都有效。

4

2 回答 2

3

不要对template-parameter-list中语法中的class关键字感到困惑。也就是说,那里的关键字并不表示实际的(甚至没有给定名称的类),而是将在模板参数列表中推导或指定的类型的名称。或者,(我更喜欢),您可以使用关键字,它可以更好地表达其含义:class ClassBclasstypename

那是:

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名称会影响声明。在函数的范围内,这是在模板参数列表中推导或指定的类型的名称。也就是说,它实际上可以是任何东西:funcclass ClassB

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实例具有相同的类型参数,而第一个声明,如前所述,可以匹配任何类型作为第二个。

换句话说,在第一个例子中,模板实参推导机制对于第一个参数的类型被限制为只推导声明中的类型,而TClassA<T>推导第二个参数的类型时不受任何限制。

于 2014-09-30T16:52:17.493 回答
1

类模板不是类,函数模板也不是函数,它们只是用于制作它们的模板。

因此,难怪您不能在需要类型相应功能的地方使用模板。

模板参数的名称与其范围之外的函数参数的名称具有相同的重要性:
无论如何都没有。在它们的范围内,它们自然会从外部范围中隐藏名称。

因此,令牌T可能不表示您尝试声明(并另外定义)您的函数的任何内容。
ClassB一个模板中,它作为模板参数名称,表示 teplate 参数,而不是一些可能碰巧存在的外部范围类。

于 2014-09-30T16:43:56.237 回答