SFINAE与is_base_of

SFINAE:即Substitution Failure Is Not an Error!可以理解为匹配失败不是错误,更严格的说应该是参数匹配失败不是一个编译时错误。

C++函数匹配的顺序遵循的原则是按照以下顺序

1.寻找参数的完美匹配函数,找到则使用

2.寻找模板函数,若实例化后的函数能够匹配则使用

3.通过默认类型转换后的参数去匹配,找到则使用

4.匹配失败,提示函数匹配错误

下面通过实现is_base_of来说明SFINAE的一般用法,来自于

http://stackoverflow.com/questions/2910979/how-does-is-base-of-work

1.定义

 1 namespace blog {
 2     template <class D, class B>
 3     struct ConversionHelper
 4     {
 5         struct Host
 6         {
 7             operator B() const;
 8             operator D();
 9         };
10         typedef char(&yes)[1];
11         typedef char(&no)[2];
12         template <typename T>
13         static yes Test(D, T);
14         static no Test(B, int);
15     };
16 
17     template <class D, class B>
18     struct Conversion
19     {
20         typedef ConversionHelper<D, B> H;
21 
22 typedef typename H::Host Host; 23 enum { exists = sizeof(typename H::yes) == sizeof(H::Test(Host(), int())) }; 24 enum { exists2Way = exists && Conversion<B, DD>::exists }; 25 enum { sameType = false }; 26 }; 27 28 template <class D> 29 struct Conversion<D, D> 30 { 31 enum { exists = 1, exists2Way = 1, sameType = 1 }; 32 }; 33 34 template <class D> 35 struct Conversion<void, D> 36 { 37 enum { exists = 1, exists2Way = 0, sameType = 0 }; 38 }; 39 40 template <class D> 41 struct Conversion<D, void> 42 { 43 enum { exists = 1, exists2Way = 0, sameType = 0 }; 44 }; 45 46 template <> 47 struct Conversion<void, void> 48 { 49 public: 50 enum { exists = 1, exists2Way = 1, sameType = 1 }; 51 }; 52 53 template<typename B, typename D> 54 struct is_base_of { 55 enum { 56 value = (me::Conversion<const D*, const B*>::exists && !me::Conversion<const B*, const void>::sameType) 57 }; 58 }; 59 }

 

1 template<typename B,typename D>
2 struct is_base_of {
3     enum {
4         value = (Conversion<const D*, const B*>::exists && !Conversion<const B*, const void>::sameType)
5     };
6 };

2.使用

1 struct A{};
2 struct B{};
3 struct C : public B
4 {
5     static_assert(blog::is_base_of<C, B>::value, "B is not the base of C");
6     //static_assert(std::is_base_of<C, B>::value, "B is not the base of C");
7 };

  在上面代码中,由于std::is_base_of<C,B>在struct C结构体中,C还没有定义完整,因此会出错。

  而blog::is_base_of<C,B>使用的是指针转换,当转换存在时,ConversionHelper::Test(D,T)

posted @ 2016-07-05 17:06  goooon  阅读(861)  评论(0编辑  收藏  举报