标签:std 方法 end blank track mic default 不同 detail
前篇文章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>,否则
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); }这个列子非常easy。不解释!
标签:std 方法 end blank track mic default 不同 detail
原文地址:http://www.cnblogs.com/mthoutai/p/7142473.html