C++判断某个类是否有某个成员函数,如果有则调用

需求

有两个SDK版本,A版本类Base有setScalingMode函数,B版本类Base无setScalingMode函数, 为了同时兼容两个SDK版本,共用一套代码,常见的是通过宏隔离,但版本众多时管理起来会很麻烦,若可先判断是否含有该函数,若有则调用,C++11新增特性解决了这一问题

//伪代码

// 如果支持setScalingMode
if(hassetScalingMode())
{
    //do something
    setScalingMode() 
}

基本知识

SFINAE:Substitution Failure Is Not An Error

匹配失败不是错误。就是说,匹配重载的函数 / 类时如果匹配后会引发编译错误,这个函数 / 类就不会作为候选(不会报错)。这是一个 C++11 的新特性,也是 enable_if 最核心的原理,其作用是当我们在进行模板特化的时候,会去选择那个正确的模板

decltype 求表达式的类型

推导表达式的类型,但不会执行表达式

int i;
double t;
struct A { double x; };
const A* a = new A();
decltype(a) x1;  //x1 是 A*
decltype(i) x2;  //x2 是 int
decltype(a -> x) x3;  // x3 是 double

std::declval  返回一个类型的右值引用

不管是否有默认构造函数或该类型不可以创建对象。(可以用于抽象基类); 

 

判断是否含有某个函数

template<typename T>
bool CkHasSetScalingMode(decltype(std::declval<T>().setScalingMode(std::declval<int>())) *test = nullptr)
{
	return true;
}

template<typename T>
bool CkHasSetScalingMode(...)
{
	return false;
}

调用方式
CkHasSetScalingMode<className>(nullptr)

template<typename T>struct hasSet
{
private:
    template<typename U> static auto Check(int) -> decltype(std::declval<U>().setScalingMode(std::declval<int>()), std::true_type());
    template<typename U> static auto Check(...) -> decltype(std::false_type());
public:
static const bool value = std::is_same<decltype(Check<T>(0)), std::true_type>::value;
}; 

使用方式
hasSet<className>::value 

函数存在则执行

template<typename T>
int b2hGbp(...) {
	cout << "not support setScalingMode" << endl;
	return -1;
};
 
template <typename T, void (T::*)(int mode) = &T::setScalingMode>
int b2hGbp(T *t, int mode) {
    t->setScalingMode(mode);
	return 0;
};


//该方案需先识别是含有该函数
/*template<typename T>
int b2hGbp(typename std::enable_if<hasSet<T>::value, T>::type *t, int mode) {
	cout << "b2hGbp 2.---------------------" << endl;
    t->setScalingMode(mode);
	return 0;
};*/

std::enable_if 

定义如下,只有第一个参数为true时才会定义type,enable_if<true, T>::type 即为 T,而 enable_if<false, T>::type 会引发编译错误

  // Primary template.
  /// Define a member typedef @c type only if a boolean constant is true.
  template<bool, typename _Tp = void>
    struct enable_if
    { };

  // Partial specialization for true.
  template<typename _Tp>
    struct enable_if<true, _Tp>
    { typedef _Tp type; };

 

参考文档:

https://blog.csdn.net/zhx6044/article/details/47295327

SFINAE https://blog.csdn.net/zjq2008wd/article/details/58180334

https://www.jianshu.com/p/45a2410d4085

enable_if  https://blog.csdn.net/jeffasd/article/details/84667090

https://ouuan.github.io/post/c-11-enable-if-%E7%9A%84%E4%BD%BF%E7%94%A8/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值