最近在看ceph rgw的源码, 在其客户端数据处理部分遇到std::enable_if的概念,如下:
template<typename DecorateeT>
class DecoratedRestfulclient:***{
***
template <typename T = void, typename std::enable_if< ! std::is_pointer<DecorateeT>::value, T>::type* = nullptr> DerefedDecorateeT& get_decoratee() { return decoratee; } template <typename T = void, typename std::enable_if< std::is_pointer<DecorateeT>::value, T>::type* = nullptr> DerefedDecorateeT& get_decoratee() { return *decoratee; }
***
}
enable_if的作用主要用于模板的匹配,偏特化的一个过程。编译器在类型推导的过程中,会尝试推导所有的重载函数,在此过程在过程中,如果enable_if条件不满足,则会在候选函数集合中剔除此函数。
如上代码,如果DecorateeT是一个指针类型,则匹配第二个,非指针类型则匹配第一个函数。std::is_pointer判断是否是指针。
以下是一个测试用例:
#include<iostream> class AJX{ int a; int j; public: explicit AJX(int a, int j):a(a),j(j){} AJX(const AJX& rhs){ a = rhs.a; j = rhs.j; } AJX& operator=(const AJX& rhs){ a = rhs.a; j = rhs.j; return *this; } AJX(AJX&& rhs){ a = rhs.a; j = rhs.j; rhs.a = 0; rhs.j = 0; } friend std::ostream& operator<<(std::ostream& out, const AJX& rhs){ out<<"AJX: "<<rhs.a<<" "<<rhs.j<<" "; return out; } ~AJX(){} }; template<typename DecorateeT> class Decorate{ DecorateeT decoratee; typedef typename std::remove_pointer<DecorateeT>::type DerefedDecorateeT; public: template <typename T = void,typename std::enable_if<! std::is_pointer<DecorateeT>::value, T>::type* = nullptr> DerefedDecorateeT& get_decoratee() { std::cout<<"Call ref"<<std::endl; return decoratee; } template <typename T = void, typename std::enable_if<std::is_pointer<DecorateeT>::value, T>::type* = nullptr> DerefedDecorateeT& get_decoratee() { std::cout<<"Call pointer"<<std::endl; return *decoratee; } Decorate(DecorateeT&& decoratee) : decoratee(std::forward<DecorateeT>(decoratee)) { } Decorate()=delete; Decorate& operator=(Decorate& decorate){ decoratee(std::forward<DecorateeT>(decorate.decoratee)); return *this; } ~Decorate(){} }; template<typename T> Decorate<T> add_decorate(T&& t){ return Decorate<T>(std::forward<T>(t)); } int main(int args, char* argv[]){ AJX test(2,3); auto tt = add_decorate(&test); std::cout<<tt.get_decoratee()<<std::endl; auto ts = add_decorate(std::move(test)); std::cout<<ts.get_decoratee()<<std::endl; }
输出如下:
[root@localhost cpp_test]# ./test_enable Call pointer AJX: 2 3 Call ref AJX: 2 3
可以看出其根据不同的参数类型调用了不同的模板函数。