近期看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. D2. Toy Train

    D2. Toy Train time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  2. 关闭 将jar或者aar发布到到mvn 中(用github作为仓库), 通过gradle dependency 方式集成

    使用Android Studio开发的用户,都希望通过maven远程仓库的方式来集成jar.aar文件,但是这些文件时如何发布的呢? 通常开发者都会将jar文件发布到sonatype上,以提供给其他开 ...

  3. go的指针学习

    1)指针是什么? 一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址 说白了就是可以先存储内存的地址,在用内存地址找到对应值 2)go中的使用 Go 语言的取地址符是 &,放到一个 ...

  4. Spring Data Redis入门示例:Hash操作(七)

    将对象存为Redis中的hash类型,可以有两种方式,将每个对象实例作为一个hash进行存储,则实例的每个属性作为hash的field:同种类型的对象实例存储为一个hash,每个实例分配一个field ...

  5. python3+beautifulSoup4.6抓取某网站小说(二)基础功能设计

    本章学习内容:1.网页编码还原读取2.功能设计 stuep1:网页编码还原读取 本次抓取对象: http://www.cuiweijuxs.com/jingpinxiaoshuo/ 按照第一篇的代码来 ...

  6. Codeforces Beta Round #93 (Div. 2 Only) (Virtual participation)

    A 相邻点对距离和*k B (Σ(v/2))/2 C 一直想不到"最优"是怎么体现的,发现y2=y1*(t1-t0)/(t0-t2),就写了1e6的枚举,然而又一些特殊情况没考虑到 ...

  7. 初识 Bootstrap

    Bootstrap 概述 Bootstrap 是一个前端框架,使用它可以快速开发响应式页面,还能专门针对 PC 端或移动端快速开发,大大提高了开发效率. Bootstrap 是最受欢迎的 HTML.C ...

  8. [Python3网络爬虫开发实战] 1.7.3-Appium的安装

    Appium是移动端的自动化测试工具,类似于前面所说的Selenium,利用它可以驱动Android.iOS等设备完成自动化测试,比如模拟点击.滑动.输入等操作,其官方网站为:http://appiu ...

  9. wepy.request 请求成功但是不进入success和fail方法,及请求传参问题

    1.根据wepy官方给的文档如下,用then拿后台返回的数据,如果用then报错,请先在app.wpy中配置promise. 没有success,fail,complete方法,如若用了也是不会进入方 ...

  10. 启用Windows10的Linux子系统并安装图形界面

    前言 目前市面上的PC电脑主要运行着四大类系统,它们分别是微软的Windows.苹果的MacOS.Linux的发行版以及Unix类系统.其中Linux和Unix都是开源的,因此市面出现的众多基于Lin ...