boost enable_if——SFINAE(匹配失败不是错误)

让我们看下这段程序:
1348106927_54.jpg

很简单的一个重载;如我所愿,程序正常运行结果如下:
void func(int)
void func(T) [with T = Test]

现在,取消最后一行的注释,再次编译。。。
出现了如下编译错误:
test0.cc: In function ‘void func(T) [with T = short int]’:
test0.cc:28:   instantiated from here
test0.cc:12: error: ‘short int’ is not a class, struct, or union type

一定很疑惑为什么编译器不会将short提升为int来选择第一个普通函数重载?
毕竟从函数签名来看,编译器不认为第一个函数是最合适的~
下面我们来尝试解决这个问题。
1.尝试给第二个函数的签名添加足够的信息。
第二个函数需要T内嵌有type类型,因此,修改签名,
给它添加一个参数类型 typename T::type且带默认值。
  1. template <typename T>  
  2. void func(T t, typename T::type  = typename T::type())  
  3. {  
  4.   typedef typename T::type type;  
  5.   
  6.   std::cout << __PRETTY_FUNCTION__ << std::endl;  
  7. }  

重新编译,通过,运行结果如下:
void func(int)
void func(T, typename T::type) [with T = Test]
void func(int)
如我们所愿,第三个以short为参数进行的调用,匹配了第一个函数。
由于SIFNAE原理,编译器尽量不会让匹配失败产生错误,它知道short没有内嵌type类型,所以它把第二个函数从重载决议候选集合中删除了,因此只能匹配第一个,且将short提升为int。

2.另一种尝试
上述做法修改了函数的签名,能够尽量不对现有函数做改动呢?
boost给了一种方法:enable_if,充分利用了SIFNAE原理。
顾名思义,在给定条件满足时,不会将函数从重载候选集中排除,否则~~

它的代码非常简单:
  1. template <bool, typename T = void >  
  2. struct enable_if  
  3. {  
  4.     typedef T type;  
  5. };  
  6.   
  7. template <typename T >  
  8. struct enable_if<false, T>  
  9. {  
  10. };  
现在我们开始修改第二个函数:
  1. template <typename T>  
  2. typename enable_if<has_type<T, typename T::type>::value , void>::type func(T )  
  3. {  
  4.     typedef typename T::type type;  
  5.   
  6.     std::cout << __PRETTY_FUNCTION__ << std::endl;  
  7. }  

has_type的含义是:T是否有内嵌类型type,如果有,value为true;它的实现先不管。
这里的意思就是:如果T没有内嵌类型type,那么value为false,这样enable_if匹配了空模板,没有内嵌的type,由于SFINAE,该函数将不会被选择。
否则,如果T有内嵌类型type,那么value为true,enable_if将匹配基模板,拥有内嵌类型,这里为void,也即是该函数的返回类型。该函数将会被选择。
运行结果如下:
void func(int)
typename enable_if<has_type<T,typename T::type>::value, void>::type func(T) [with T = Test]
void func(int)

最后贴一下has_type的实现,自己写的,估计有不对的地方,先放着后面看。
1348121135_96.jpg
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值