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

这段代码很简单判断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);
}

呵呵。。。很简单,可是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);
	}

这个列子很简单,不解释!

boost::mpl::eval_if的用法

时间: 2024-11-08 21:41:51

boost::mpl::eval_if的用法的相关文章

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 m

boost::signals::signal的用法

吃力的讲完boost::signals的ppt,然后接着就是做练习题.通过讲ppt,发现有一句话说的真好:你自己知道是一回事,你能给别人讲明白又是另外一回事.真的有些东西你自己理解,但是用语言去很难表达,是不是用语言难以表达暴露出自己对所理解的东西不是真正的理解?....orz,不过讲完ppt之后,真的对boost::singals的理解又加深一层.好了废话不多说了,现在来看两个习题(ppt的内容基本上是boost官方网站介绍boost::singlas用法的章节,这里不贴了): 第一题: 题目

boost::any的一般用法

01.#include <iostream> 02.#include <list> 03.#include <boost/any.hpp> 04. 05.typedef std::list<boost::any> list_any; 06. 07.//关键部分:可以存放任意类型的对象 08.void fill_list(list_any& la) 09.{ 10.    la.push_back(1000);//存放常数 11.    la.push

boost信号量 boost::interprocess::interprocess_semaphore的用法

使用方法首先给信号量初始化赋值,可以根据需要设定需要的值,之前在写项目的过程中用这个控制下载的线程个数. 1 boost::interprocess::interprocess_semaphore m_semaphore(0); 然后就是pv操作了,v操作就只有一个post(),post()一次,信号量加1.p操作有三个,看函数名字都很明显知道是什么意思, wait(),try_wait() ,timed_wait(const boost::posix_time::ptime&abs_time)

windows下boost库的基本用法

由于boost都是使用模板的技术,所以全部代码都是写在一个.hpp头文件里.这样boost中的大部分内容是不须要编译生成对应的链接库,仅仅须要设置以下的包括文件夹(或者设置一下环境变量),在源文件里包括对应的头文件就能够使用了. 少部分库须要生成链接库来使用. 以下介绍完整安装boost库的方法: 1.首先到boost官网去下载最新的版本号的boost库: http://www.boost.org/ 2.解压文件.在命令提示符中打开到boost库的根文件夹下: 双击bootstrap.bat文件

boost.multi_array 的基本用法(2)

//made by davidsu33 //2014-9-14 11:51 #include "stdafx.h" #include <boost/config.hpp> #include <boost/multi_array/extent_gen.hpp> #include <boost/multi_array.hpp> #include <boost/pool/pool.hpp> #include <boost/pool/poo

Boost Log 基本用法

Boost Log 基本用法 flyfish 2014-11-5 根据boost提供的代码示例,学习Boost Log 的基本用法 前提 boost版本boost_1_56_0 示例代码文件夹 boost_1_56_0\libs\log\example\basic_usage 使用的单词很形象,整个过程就像流水一样 假设要输出的日志比作水 水                     (Hello, World!) 水槽                 (sink) 流向哪里        (co

boost::serialization 拆分serialize函数

在前篇 boost::serialization 用基类指针转存派生类(错误多多,一波三折)文中我们都是使用serialize函数来实现序列化,其代码格式如下: private: friend class boost::serialization::access; template<typename Archive> void serialize(Archive& ar, const unsigned int version) { ar & BOOST_SERIALIZATIO

Effective C++ 条款55 让自己熟悉Boost

1. Boost是一个C++开发者集结的社群,也是一个可自由下载的C++程序库群,它的网址是http://Boost.org.C++组织和网站有很多,但Boost有两个特性是其他组织无可匹敌的:第一,Boost由C++标准委员会成员创设,因此和C++标准委员会之间有着独一无二的密切关系,作为一个"可被加入标准C++之各种功能"的测试场是Boost的目标之一,实际上,以TR1(见条款54)提案进入标准C++的14个新程序库,超过三分之二奠基于Boost的工作成果.第二,它以公开的同僚复审