最近在看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
可以看出其根据不同的参数类型调用了不同的模板函数。
网友评论