C++11 SFINEA规则_判断类是否存在某个成员函数

在C++模板中,SFINEA规则是指”Substitution failure is not an error“(匹配失败不是错误)。具体来说,就是当重载的模板参数展开时,如果展开导致一些类型不匹配,编译器并不报错。

我们可以使用这个规则来判断类是否存在某个成员函数,请看下面的实例:

#include<iostream>
#include<utility>
#include<type_traits>

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

struct myStruct
{
    void foo() { std::cout << "hello" << std::endl;  }
};

struct another
{
    void test() { std::cout << "test" << std::endl;  }
};

int main()
{
    if( has_member_foo<myStruct>::value )
    	std::cout << "myStruct has foo funciton"  << std::endl;
    else
        std::cout << "myStruct does't have foo funciton"  << std::endl;

    if( has_member_foo<another>::value )
    	std::cout << "another has foo function"  << std::endl;
    else
	std::cout << "another does't have foo function"  << std::endl;
    return 0;
}
这个has_member_foo的作用就是检查类型是否存在非静态成员foo函数

具体的实现思路是这样的:定义两个重载函数Check,由于模板实例化的过程中会优先选择匹配程度最高的重载函数,在模板实例化的过程中检查类型是否存在foo函数,如果存在则返回std::true_type,否则返回std::false_type. 巧妙的利用了C++的SFINAE特性.


template<typename U> static auto Check(int) -> decltype(std::declval<U>().foo(), std::true_type());

最关键的一句代码: 配合decltype来获取函数foo的返回类型,如果获取成功则表明存在foo函数,否则就会替换失败,而选择默认的Check函数(不会报错,SFINAE)。decltype在这里还有另外一个妙用,它可以通过逗号表达式连续推断多个函数的返回类型.

运行截图:


  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ 中,可以使用静态成员函数作为信号处理函数,并且这个静态成员函数可以访问的私有成员变量。因此,你可以将 `sa_sigaction` 设置为一个静态成员函数,然后在这个静态成员函数中访问该的其他成员变量。 下面是一个示例代码: ```c++ class MyClass { public: void myMemberFunction(int signal_number) { // 在这里实现信号处理函数的功能 } static void myStaticMemberFunction(int signal_number, siginfo_t* info, void* context) { // 需要将 sa_sigaction 绑定到 myMemberFunction 上 MyClass* obj = reinterpret_cast<MyClass*>(info->si_value.sival_ptr); obj->myMemberFunction(signal_number); } private: // 声明 sigaction 型的成员变量 struct sigaction my_sa; }; int main() { MyClass obj; // 绑定信号处理函数 obj.my_sa.sa_sigaction = &MyClass::myStaticMemberFunction; obj.my_sa.sa_flags = SA_SIGINFO; obj.my_sa.sa_restorer = nullptr; // 在这里设置其他的 sigaction 相关参数 // 安装信号处理函数 sigaction(SIGINT, &obj.my_sa, nullptr); // 在这里执行其他的代码 return 0; } ``` 在上面的代码中,我们将 `sa_sigaction` 设置为了一个静态成员函数 `myStaticMemberFunction`,并在这个静态成员函数中将 `sa_sigaction` 绑定到了成员函数 `myMemberFunction` 上。在 `main` 函数中,我们创建了 `MyClass` 的一个对象 `obj`,并将 `obj.my_sa.sa_sigaction` 设置为了 `MyClass::myStaticMemberFunction`。最后,我们使用 `sigaction` 函数安装了信号处理函数。 需要注意的是,因为 `sa_sigaction` 的型是 `void(*)(int, siginfo_t*, void*)`,所以 `myStaticMemberFunction` 的参数列表也必须与此匹配。在 `myStaticMemberFunction` 中,我们通过 `reinterpret_cast` 将 `si_value.sival_ptr` 转换为 `MyClass*` 型,然后再通过这个指针调用 `obj->myMemberFunction`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值