近期看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的使用方法的更多相关文章

  1. windows下boost库的基本使用方法

    因为boost都是使用模板的技术,所以所有代码都是写在一个.hpp头文件中.这样boost中的大部分内容是不需要编译生成相应的链接库,只需要设置下面的包含目录(或者设置一下环境变量),在源文件中包含相 ...

  2. boost::signals::signal的使用方法

    吃力的讲完boost::signals的ppt.然后接着就是做练习题. 通过讲ppt,发现有一句话说的真好:你自己知道是一回事.你能给别人讲明确又是另外一回事.真的有些东西你自己理解,可是用语言去非常 ...

  3. boost::filesystem经常使用使用方法具体解释

    提示: filesystem库提供了两个头文件,一个是<boost/filesystem.hpp>,这个头文件包括基本的库内容.它提供了对文件系统的重要操作. 同一时候它定义了一个类pat ...

  4. boost::any的一般使用方法

    01.#include <iostream>    02.#include <list>    03.#include <boost/any.hpp>    04. ...

  5. Boost Log 基本使用方法

    Boost Log 基本使用方法 flyfish 2014-11-5 依据boost提供的代码演示样例,学习Boost Log 的基本使用方法 前提 boost版本号boost_1_56_0 演示样例 ...

  6. Boost 和 STL 相比有哪些优势和劣势?

    1. 在设计原则上,STL和Boost大体统一因为STL和Boost基本上都是标准委员会那批人在策划.审核和维护,所以口味上是相对接近的.但是因为Boost并不在标准中,或者说是下一代标准的试验场,所 ...

  7. Boost 1.61.0 Library Documentation

    http://www.boost.org/doc/libs/1_61_0/ Boost 1.61.0 Library Documentation Accumulators Framework for ...

  8. Boost 序列化

    原文链接: https://blog.csdn.net/qq2399431200/article/details/45621921 1. 编译器 gcc, boost 1.55 2.1第一个简单的例子 ...

  9. Boost.Accumulators累加器的简单使用

    Boost.Accumulators是一个累加器,实现的功能很简单,就是对一组数据进行操作,然后可以得到一些特征数据. 由于累加器默认不对数据进行储存操作,所以不能把它作为一个简单的容器使用. 简单使 ...

随机推荐

  1. col - 过滤掉输入中的反向换行符

    SYNOPSIS(总览) col [-bfx ] [ Fl l Ar num ] DESCRIPTION(描述) Col 过滤掉反向(以及半反向)换行符(LF: line feed or NL: ne ...

  2. cocos2dx游戏如何架构

    声明:此篇文章不介绍如何使用cocos2dx制作游戏.站在架构师的角度如果制作游戏. 以我多年的游戏开发经验,和其他技术积累, 市面的所谈的一些软件架构模式都不太适合游戏软件. 我指的架构模式,MVC ...

  3. Caffe结构

    caffe可以分为3层结构:blob,layer,net 在layer中,input data用bottom表示,output data用top表示.每一个layer定义了三种操作,setup(Lay ...

  4. MFC中调用Windows API函数的方式

    windows aoi 函数的调用前面加::

  5. Python中yield函数浅析

    带有yield的函数在Python中被称之为generator(生成器),下面我们将使用斐波那契数列来举例说明下该函数:(环境是在Python3.x下)  如何生成斐波那契数列: 斐波那契(Fibon ...

  6. getDate() 获取时间 如2018年09月21日 11:32:11

    function p(s) { return s < 10 ? '0' + s: s;} function getDate() { var myDate = new Date(); //获取当前 ...

  7. 零基础入门学习Python(5)--闲聊之Python的数据类型

    前言 本次主要闲聊一下python的一些数值类型,整型(int),浮点型(float),布尔类型(bool),还有e记法(科学计数法),也是属于浮点型. 数值类型介绍 整型 整型就是我们平时所说的整数 ...

  8. 安装lnmp

    一.yum安装php 1.更新更新yum源:rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rp ...

  9. Python之面向对象继承和派生

    Python之面向对象继承和派生 什么是继承: 继承是一种创建新的类的方法.在Python中,新建的类可以继承自一个或多个父类.原始类称为基类或超类. 新建的类称为派生类或子类. Python中类的继 ...

  10. Inspector's Dilemma(欧拉通路)

    In a country, there are a number of cities. Each pair of city is connected by a highway, bi-directio ...