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在这里还有另外一个妙用,它可以通过逗号表达式连续推断多个函数的返回类型.

运行截图:


猜你喜欢

转载自blog.csdn.net/qq_31175231/article/details/77479692