编写专用于类及其子类的函数模板 [英] Writing a function template that is specialised for a class and its subclasses
问题描述
我想写一个函数模板。对于不满足其他版本标准的所有类型,应使用一个版本;当参数是给定类的基类时,或者该类本身时,应使用其他版本。
I am trying to write a function template. One version should be used for all types that don't satisfy the criteria for the other version; the other version should be used when the argument is a base class of a given class, or that class itself.
我已经尝试为 Base&
,但是当类从 Base
派生时,它们使用通用类,而不是特定类。
I have tried doing an overload for Base&
, but when classes are derived from Base
, they use the general one, not the specific one.
我也试过这个SFINAE方法:
I also have tried this SFINAE approach:
struct Base { };
struct Derived : public Base { };
struct Unrelated { };
template<typename T>
void f(const T& a, bool b = true) {
cout << "not special" << endl;
}
template<typename T>
void f(const Base& t, bool b = is_base_of<Base, T>::value) {
cout << "special" << endl;
}
Base b;
Derived d;
Unrelated u;
f(b); f(d); f(u);
但是所有的都打印不特殊。我不善于SFINAE,我可能只是做错了。如何写这样的函数?
But all of them print "not special". I am not good at SFINAE and I am probably just doing it wrong. How can I write a function like this?
推荐答案
首先,这些都不会调用特殊 f
重载,因为 T
不能从函数参数中推导出来。它的第一个参数需要是 T
类型:
First, none of these will ever call the "special" f
overload because T
cannot be deduced from the function arguments. Its first parameter needs to be of type T
:
void f(const T& t, bool b = is_base_of<Base, T>::value)
done,注意特殊重载并不真正使用SFINAE来影响重载分辨率: is_base_of< T,U> :: value
总是有一个值: code> true 或 false
。要影响重载解析,您需要使用 enable_if
,它根据布尔值有条件地定义类型。
Once that is done, note that the "special" overload doesn't really use SFINAE to affect overload resolution: is_base_of<T, U>::value
always has a value: it's either true
or false
. To affect overload resolution, you need to use enable_if
, which conditionally defines a type based on a boolean value.
此外,两个重载都需要使用SFINAE:如果 T
是从基础派生的(或是基本类型),必须启用特殊 只有当 T
不是从基数派生时,才必须启用重载,否则会出现重载解决模糊。
Also, both overloads need to use SFINAE: the "special" overload must be enabled if T
is derived from the base (or is the base type), and the "not special" overload must be enabled only if T
is not derived from the base, otherwise there will be overload resolution ambiguities.
两个重载应该被声明并定义为:
The two overloads should be declared and defined as:
template<typename T>
void f(T const& a, typename enable_if<!is_base_of<Base, T>::value>::type* = 0)
{
cout << "not special" << endl;
}
template<typename T>
void f(T const& t, typename enable_if<is_base_of<Base, T>::value>::type* = 0)
{
cout << "special" << endl;
}
最后,注意这里没有专业化。这两个名为 f
的函数是重载。
Finally, note that there is no specialization here. These two functions named f
are overloads.
这篇关于编写专用于类及其子类的函数模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!