前篇文章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>,否则
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
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用法。现在我们
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);
}下面还有一个列子,这是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的用法,布布扣,bubuko.com
原文地址:http://blog.csdn.net/xiaoliangsky/article/details/25083283