boost::mpl::eval_if的使用方法
近期看boost的时候总是遇见这个eval_if,不知道啥意思,就没法看下去了,比方
前篇文章boost::serialization 拆分serialize函数分析时就出现这样一段代码:
template<class Archive, class T>
inline void split_member(Archive & ar, T & t, const unsigned int file_version)
{
typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
BOOST_DEDUCED_TYPENAME Archive::is_saving,
mpl::identity<detail::member_saver<Archive, T> >,
mpl::identity<detail::member_loader<Archive, T> >
>::type typex;
typex::invoke(ar, t, file_version);
}
就去看看boost文档解释例如以下:
typedef eval_if<c,f1,f2>::type t;
Return type: Any type.
Semantics: If c::value == true, t is identical to f1::type; otherwise t is identical to f2::type.
就是增加c::value 为TRUE就返回f1::type,否则就返回f2::type。
然后给了一个一列子:
typedef eval_if< true_, identity<char>, identity<long> >::type t1;
typedef eval_if< false_, identity<char>, identity<long> >::type t2; BOOST_MPL_ASSERT(( is_same<t1,char> ));
BOOST_MPL_ASSERT(( is_same<t2,long> ));
自己动手试试。使用方法还是蛮简单的,并且还能够递归有用。
看以下一个简单的样例:
//定义两个结构体
template<typename T>
struct PointerStruct
{
typedef T* PointerT;
static void print()
{
std::cout << typeid(PointerT).name() << std::endl;
}
}; template<typename T>
struct DefaultStruct
{
static void print()
{
std::cout << "default is called!" << std::endl;
}
};
然后来实现一个推断T是否是指针类型:
typedef
typename boost::mpl::eval_if<//#1
boost::is_pointer<T>, boost::mpl::identity<PointerStruct<T>>,
boost::mpl::identity<DefaultStruct<T>>
>::type typex;//#1
这段代码非常easy推断T是否是一个指针,假设true,那么type的类型就是PointerStruct<T>,否则
type的类型是默认 DefaultStruct<T>。够简单吧,应该会用了吧。好。我们来个复杂一点的,由于
一个eval_if仅仅能推断一个类型。
我们想推断两个类型:
typedef
BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<//#1
boost::is_pointer<T>, boost::mpl::identity<PointerStruct<T> >,
BOOST_DEDUCED_TYPENAME eval_if<//#2
boost::is_array<T>, boost::mpl::identity<ArrayStruct<T> >,
boost::mpl::identity<DefaultStruct<T>>
>//#2
>::type typex;//#1
注意#1 #2是成对出现的,这就是递归模板的一个典型应用!这样就能够推断两个类型的:是指针韩式数组
以下示范了可以推断多类型的列子:
typedef
BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<//#1
boost::is_pointer<T>, boost::mpl::identity<PointerStruct<T> >,
BOOST_DEDUCED_TYPENAME eval_if<//#2
boost::is_array<T>, boost::mpl::identity<ArrayStruct<T> >,
BOOST_DEDUCED_TYPENAME eval_if<//#3
boost::is_class<T>, boost::mpl::identity<ClassStruct<T> >,
BOOST_DEDUCED_TYPENAME eval_if<//#4
boost::is_enum<T>, boost::mpl::identity<EnumStruct<T> >,
boost::mpl::identity<DefaultStruct<T> >
>//#4
>//#3
>//#2
>::type typex;//#1
如今我们已经可以写出推断任一类型(boost支持非常多类型的推断)的eval_if使用方法。如今我们
应该想想怎么应用 eval_if 。看到结构体里面的print函数吗。我们能够为不同的类型实现
不同的print方法,然后在确定类型后我们仅仅须要调用:
typex::print();
比方T是一个pointer,那么typex的类型就是PointerStruct<T>,那么上面哪句代码就等于调用:
PointerStruct<T>::print();
这样是不是非常厉害,增加我们有非常多不同的方法要调用时,我们能够给每一个方法用结构体包装,
然后在这个结构体里面实现方法。
然后用类型去确定调用那些方法。
首先实现用结构体包装我们要调用的方法:
为简单这里仅实现输出类型....
template<typename T>
struct PointerStruct
{
typedef T* PointerT;
static void print()
{
std::cout << typeid(PointerT).name() << std::endl;
//do what you want to do...
}
}; template<typename T>
struct EnumStruct
{
static void print()
{
std::cout << typeid(T).name() << std::endl;
//do what you want to do...
}
}; template<typename T>
struct ArrayStruct
{
static void print()
{
std::cout << "this is " << typeid(T).name() << std::endl;
//do what you want to do...
}
}; template<typename T>
struct ClassStruct
{
static void print()
{
std::cout << typeid(T).name() << std::endl;
//do what you want to do...
}
}; template<typename T>
struct DefaultStruct
{
static void print()
{
std::cout << "default is called!" << std::endl;
//do what you want to do...
}
};
然后在实现一个包装eval_if的函数,在这个函数里面实现依据类型来调用对应的函数:
template<typename T>
inline void printTypeOfT(const T& t)
{
using namespace boost::mpl;
typedef
BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<//#1
boost::is_pointer<T>, boost::mpl::identity<PointerStruct<T> >,
BOOST_DEDUCED_TYPENAME eval_if<//#2
boost::is_array<T>, boost::mpl::identity<ArrayStruct<T> >,
BOOST_DEDUCED_TYPENAME eval_if<//#3
boost::is_class<T>, boost::mpl::identity<ClassStruct<T> >,
BOOST_DEDUCED_TYPENAME eval_if<//#4
boost::is_enum<T>, boost::mpl::identity<EnumStruct<T> >,
boost::mpl::identity<DefaultStruct<T> >
>//#4
>//#3
>//#2
>::type typex;//#1 typex::print();//公共接口
}
这样ok了,如今測试一个:
class TestClass
{
}; enum Type
{
a,b,c
};
void fun0()
{
int* pInt = NULL;
printTypeOfT(pInt);
Type xT;
printTypeOfT(xT);
float Array[] = {0.0f, 1.0f};
printTypeOfT(Array);
TestClass TC;
printTypeOfT(TC);
float yF;
printTypeOfT(yF);
}
呵呵。。。非常easy,但是eval_if却是有非常多宏来实现的,有些宏没看懂!。
。。先会用再说!
以下另一个列子,这是boost::serialization 拆分serialize函数里面那个split_member函数就是採用eval_if来实现,
这里简单模拟一个:
class text_iarchive
{
public:
typedef boost::mpl::bool_<true> is_loading;
typedef boost::mpl::bool_<false> is_saving;
}; class text_oarchive
{
public:
typedef boost::mpl::bool_<false> is_loading;
typedef boost::mpl::bool_<true> is_saving;
}; class access
{
public:
template<typename Archive, class T>
static void save(Archive& ar, T& t,const unsigned int file_version)
{
t.save(ar, file_version);
} template<typename Archive, class T>
static void load(Archive& ar, T& t,const unsigned int file_version)
{
t.load(ar, file_version);
}
}; class test_class
{
private:
friend class access; template<typename Archive>
void save(Archive& ar, const unsigned int file_version)
{
std::cout << BOOST_CURRENT_FUNCTION << " " << &(*this) << std::endl;
} template<typename Archive>
void load(Archive& ar, const unsigned int file_version)
{
std::cout << BOOST_CURRENT_FUNCTION << " " << &(*this) << std::endl;
} }; template<typename Archive, class T>
struct member_saver
{
static void invoke(Archive& ar, T& t,const unsigned int file_version)
{
access::save(ar, t, file_version);
}
}; template<typename Archive, class T>
struct member_loader
{
static void invoke(Archive& ar, T& t,const unsigned int file_version)
{
access::load(ar, t, file_version);
}
}; template<typename Archive, class T>
void split_member(Archive& ar, T& t,const unsigned int file_version)
{
typedef
BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<
BOOST_DEDUCED_TYPENAME Archive::is_saving,
boost::mpl::identity<member_saver<Archive, T> >,
boost::mpl::identity<member_loader<Archive, T> >
>::type typex;
typex::invoke(ar, t, file_version);
} void fun()
{
text_iarchive ia;
text_oarchive oa;
test_class tc;
split_member(ia, tc, 1);
split_member(oa, tc, 1);
}
这个列子非常easy。不解释!
boost::mpl::eval_if的使用方法的更多相关文章
- windows下boost库的基本使用方法
因为boost都是使用模板的技术,所以所有代码都是写在一个.hpp头文件中.这样boost中的大部分内容是不需要编译生成相应的链接库,只需要设置下面的包含目录(或者设置一下环境变量),在源文件中包含相 ...
- boost::signals::signal的使用方法
吃力的讲完boost::signals的ppt.然后接着就是做练习题. 通过讲ppt,发现有一句话说的真好:你自己知道是一回事.你能给别人讲明确又是另外一回事.真的有些东西你自己理解,可是用语言去非常 ...
- boost::filesystem经常使用使用方法具体解释
提示: filesystem库提供了两个头文件,一个是<boost/filesystem.hpp>,这个头文件包括基本的库内容.它提供了对文件系统的重要操作. 同一时候它定义了一个类pat ...
- boost::any的一般使用方法
01.#include <iostream> 02.#include <list> 03.#include <boost/any.hpp> 04. ...
- Boost Log 基本使用方法
Boost Log 基本使用方法 flyfish 2014-11-5 依据boost提供的代码演示样例,学习Boost Log 的基本使用方法 前提 boost版本号boost_1_56_0 演示样例 ...
- Boost 和 STL 相比有哪些优势和劣势?
1. 在设计原则上,STL和Boost大体统一因为STL和Boost基本上都是标准委员会那批人在策划.审核和维护,所以口味上是相对接近的.但是因为Boost并不在标准中,或者说是下一代标准的试验场,所 ...
- Boost 1.61.0 Library Documentation
http://www.boost.org/doc/libs/1_61_0/ Boost 1.61.0 Library Documentation Accumulators Framework for ...
- Boost 序列化
原文链接: https://blog.csdn.net/qq2399431200/article/details/45621921 1. 编译器 gcc, boost 1.55 2.1第一个简单的例子 ...
- Boost.Accumulators累加器的简单使用
Boost.Accumulators是一个累加器,实现的功能很简单,就是对一组数据进行操作,然后可以得到一些特征数据. 由于累加器默认不对数据进行储存操作,所以不能把它作为一个简单的容器使用. 简单使 ...
随机推荐
- for in,Object.keys()与for of的用法与区别
Array.prototype.sayLength=function(){ console.log(this.length); } let arr = ['a','b','c','d']; arr.n ...
- vue mixins应用场景
学习知识得在应用场景中去应用,这样才能真正学到东西,记忆也深刻,以后碰到类似的东西就会了. 1.在assets文件夹下创建一个js文件 // 创建一个需要混入的对象 export const mixi ...
- CCF计算机职业资格认证考试 201809-2 买菜
以下内容过于幼稚,请大佬自觉绕道.. 题目描述: 时间限制:1.0s内存限制:256.0MB问题描述:问题描述 小H和小W来到了一条街上,两人分开买菜,他们买菜的过程可以描述为,去店里买一些菜然后去旁 ...
- 在你的Android手机上运行Linux
之前试过许多方法(也就几种),像什么Complete Linux Installer,Debian noroot,利用已有的Linux构造Bootstrap之类,要么就是复杂得要命(调了两天没有调出来 ...
- [LUOGU] P3354 [IOI2005]Riv 河流
题目描述 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海.这条大河的入海口处有一个村庄--名叫 ...
- Python数据类型方法
Python认为一切皆为对象:比如我们初始化一个list时: li = list('abc') 实际上是实例化了内置模块builtins(python2中为__builtin__模块)中的list类: ...
- CSS九宫格样式
CSS .main>div { width: 14%; min-width: 160px; padding: 2%; height: 60px; border: 1px solid #f4f4f ...
- day21 05 员工信息表
day21 05 员工信息表 假设有一个员工信息表,里面有每个员工的名字,id,年龄,电话,还有他们所作的工作,而有时候我们并不需要所有的信息,而想根据某些条件,寻找符合条件即可,即筛选, 比如想要筛 ...
- MyBatis 返回Map<String,Object>类型
<!-- 导出所有数据 --> <select id="exportAll" resultMap="map"> SELECT t1.ME ...
- js给对象添加属性
obj.prototype = shuxing: shuxing['属性']=值: function Person(){}; var person = new Person(); person.nam ...