编写专用于类及其子类的函数模板 [英] Writing a function template that is specialised for a class and its subclasses

查看:175
本文介绍了编写专用于类及其子类的函数模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写一个函数模板。对于不满足其他版本标准的所有类型,应使用一个版本;当参数是给定类的基类时,或者该类本身时,应使用其他版本。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆