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是一个累加器,实现的功能很简单,就是对一组数据进行操作,然后可以得到一些特征数据. 由于累加器默认不对数据进行储存操作,所以不能把它作为一个简单的容器使用. 简单使 ...
随机推荐
- col - 过滤掉输入中的反向换行符
SYNOPSIS(总览) col [-bfx ] [ Fl l Ar num ] DESCRIPTION(描述) Col 过滤掉反向(以及半反向)换行符(LF: line feed or NL: ne ...
- cocos2dx游戏如何架构
声明:此篇文章不介绍如何使用cocos2dx制作游戏.站在架构师的角度如果制作游戏. 以我多年的游戏开发经验,和其他技术积累, 市面的所谈的一些软件架构模式都不太适合游戏软件. 我指的架构模式,MVC ...
- Caffe结构
caffe可以分为3层结构:blob,layer,net 在layer中,input data用bottom表示,output data用top表示.每一个layer定义了三种操作,setup(Lay ...
- MFC中调用Windows API函数的方式
windows aoi 函数的调用前面加::
- Python中yield函数浅析
带有yield的函数在Python中被称之为generator(生成器),下面我们将使用斐波那契数列来举例说明下该函数:(环境是在Python3.x下) 如何生成斐波那契数列: 斐波那契(Fibon ...
- getDate() 获取时间 如2018年09月21日 11:32:11
function p(s) { return s < 10 ? '0' + s: s;} function getDate() { var myDate = new Date(); //获取当前 ...
- 零基础入门学习Python(5)--闲聊之Python的数据类型
前言 本次主要闲聊一下python的一些数值类型,整型(int),浮点型(float),布尔类型(bool),还有e记法(科学计数法),也是属于浮点型. 数值类型介绍 整型 整型就是我们平时所说的整数 ...
- 安装lnmp
一.yum安装php 1.更新更新yum源:rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rp ...
- Python之面向对象继承和派生
Python之面向对象继承和派生 什么是继承: 继承是一种创建新的类的方法.在Python中,新建的类可以继承自一个或多个父类.原始类称为基类或超类. 新建的类称为派生类或子类. Python中类的继 ...
- Inspector's Dilemma(欧拉通路)
In a country, there are a number of cities. Each pair of city is connected by a highway, bi-directio ...