最近在看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<<"\n"; 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
可以看出其根據不同的參數類型調用了不同的模板函數。