用Cpp11新template feature尝试metaprogramming
来源:互联网 发布:淘宝网站的盈利来源 编辑:程序博客网 时间:2024/04/30 13:05
Cplusplus 11 发布大半年了, 基本上浏览了一遍wiki pedia上关于新feature的介绍, 个别feature已经迅速被大家广泛运用了, 剩下的由于编译器的支持问题未敢大肆使用。由于 新标准在core language中就提供了以前要一堆template才能实现的feature以及std lib中把boost的一些container搬字过纸,所以熟悉boost的人可能一看介绍马上就懂得怎么用了。 我自己对template一直比较感兴趣, 所以很自然地对新标准中关于template的改进特别关注,这里介绍一下新标准中的变参模板, 并以此实现一下metaprogramming中的一下戏法。如果你不熟悉metaprogramming, 直接忽略本文可也。。。
关于变参模板的使用方法请参考 http://en.wikipedia.org/wiki/Variadic_templates
好了, 马上开始用新技术实现一些旧戏法(warning: 我没有写详尽的unit test,也未把以下代码用于实战,仅仅是手痒,代码你可以随便用,但是出问题了别找我!)
代码用gcc 4.6测试通过。。。
首先variadic template实现bool变量, 用以后续实现更深的条件语句,改用variadic template的好处就是可以传空模板参数,并不是纯粹为了以新换旧。
struct _error;template<bool...>struct bool_;template<bool Value>struct bool_<Value> { typedef bool_<Value> type; static const bool value = Value;//为了可以打印,其实可删除};template<>struct bool_<>: public bool_<0> {};typedef bool_<0> false_;typedef bool_<1> true_;
typedef uintmax_t pint_t;typedef intmax_t nint_t;template<pint_t...>struct PInt;template<pint_t value>struct PInt<value> { typedef PInt<value> type; static const pint_t v = value;};template<nint_t...>struct NInt;template<nint_t value>struct NInt<value> { static_assert(value < 0, "NInt value must be < 0. Otherwise, use PInt."); typedef NInt<value> type; static const nint_t v = value;};template<>struct PInt<>: public PInt<0> {};typedef PInt<0> Zero;typedef PInt<1> One;typedef PInt<2> Two;
接着是metaprogramming必须的一些component, 毫不客气地说, boost差不多也是这么实现的了。
template<class TheType>struct identity{typedef TheType type;};template<class A>struct isTrue { typedef true_ type;};template<>struct isTrue<false_> { typedef false_ type;};template<>struct isTrue< PInt<0> > { typedef false_ type;};
template<class Cond, class Then, class Else>struct _ifAux { typedef typename Then::type type;};template<class Then, class Else>struct _ifAux<false_, Then, Else> { typedef typename Else::type type;};template<class Cond, class Then, class Else>struct eval_if { typedef typename _ifAux< typename isTrue<Cond>::type, Then, Else >::type type;};
对, 为了方便测试而写的, 实际绝对不应该这么写的, 看官小心。。。
// not a good solutiontemplate<long i>struct GetInt{ typedef typename eval_if<bool_<(i<0)>, NInt<i>, PInt<i> >::type type;};
template<class A, class B>struct plus;template<pint_t val1, pint_t val2>struct plus< PInt<val1>, PInt<val2> > { typedef PInt<(val1 + val2)> type;};template<pint_t val1, nint_t val2>struct plus< PInt<val1>, NInt<val2> > { typedef typename eval_if< bool_<!((val1)<((pint_t)-val2))>, identity< PInt<(val1 - (pint_t)-val2)> >, identity< NInt<((nint_t)val1 + val2)> > >::type type;};template<nint_t val1, pint_t val2>struct plus< NInt<val1>, PInt<val2> > { typedef typename plus< PInt<val2>, NInt<val1> >::type type;};
template<class A>struct negate;template<pint_t val1>struct negate< PInt<val1> > { typedef NInt<-(nint_t)val1> type;};template<>struct negate< Zero > { typedef Zero type;};template<nint_t val1>struct negate< NInt<val1> > { typedef PInt<(pint_t)-val1> type;};
template<class A, class B>struct minus { typedef typename plus<A,typename negate<B>::type>::type type;};template<class A, int>struct spawn;template<pint_t val1, int val2>struct spawn< PInt<val1>, val2 > { typedef typename eval_if< bool_<(val2 < 0)>, identity< NInt<val2> >, identity< PInt<val2> > >::type type;};template<nint_t val1, int val2>struct spawn< NInt<val1>, val2 > { typedef typename eval_if< bool_<(val2 < 0)>, identity< NInt<val2> >, identity< PInt<val2> > >::type type;};template<nint_t val1>struct make_int { typedef typename eval_if< bool_<(val1 < 0)>, identity< NInt<val1> >, identity< PInt<val1> > >::type type;};
template<class, class, class...>struct cond;template<class Cond, class Then, class Else>struct cond<Cond,Then,Else> { typedef typename eval_if<typename Cond::type,Then,Else>::type type;};template<class Cond, class Then, class Cond2, class Then2, class... More>struct cond<Cond,Then,Cond2,Then2,More...> { typedef typename eval_if< typename Cond::type, Then, cond<Cond2,Then2,More...> >::type type;};
template<class... Cond>struct or_;template<>struct or_<> { typedef false_ type;};template<class First, class... Other>struct or_<First,Other...> { typedef typename eval_if< typename First::type, identity<true_>, or_<Other...> >::type type;};template<class... Cond>struct and_;template<>struct and_<> { typedef true_ type;};template<class First, class... Other>struct and_<First,Other...> { typedef typename eval_if< typename First::type, and_<Other...>, identity<false_> >::type type;};template<class Cond>struct _not { typedef typename eval_if< Cond, identity<false_>, identity<true_> >::type type;};
template<class A, class B> struct less;template<pint_t val1, pint_t val2>struct less< PInt<val1>, PInt<val2> > { typedef bool_<((val1)<(val2))> type;};template<nint_t val1, nint_t val2>struct less< NInt<val1>, NInt<val2> > { typedef bool_<((val1)<(val2))> type;};template<nint_t val1, pint_t val2>struct less< NInt<val1>, PInt<val2> > { typedef true_ type;};template<pint_t val1, nint_t val2>struct less< PInt<val1>, NInt<val2> > { typedef false_ type;};template<class A, class B>struct less_equal { typedef typename _not<typename less<B,A>::type>::type type;};template<class A, class B>struct greater { typedef typename less<B,A>::type type;};template<class A, class B>struct greater_equal { typedef typename less_equal<B,A>::type type;};template<class A, class B>struct equal_to { typedef typename and_<less_equal<A,B>,less_equal<B,A> >::type type;};template<class A, class B>struct not_equal_to { typedef typename _not<typename equal_to<A,B>::type>::type type;};
template<class A, class B>struct divides;template<pint_t val1, pint_t val2>struct divides< PInt<val1>, PInt<val2> > { typedef PInt<(val1 / val2)> type;};template<nint_t val1, nint_t val2>struct divides< NInt<val1>, NInt<val2> > { typedef PInt<((pint_t)-val1 / (pint_t)-val2)> type;};template<pint_t val1, nint_t val2>struct divides< PInt<val1>, NInt<val2> > { typedef typename make_int<((nint_t)val1 / val2)>::type type;};template<nint_t val1, pint_t val2>struct divides< NInt<val1>, PInt<val2> > { typedef typename make_int<(val1 / (nint_t)val2)>::type type;};template<class A>struct recip: public divides<One,A> {};template<class A>struct isOdd { typedef typename equal_to< typename divides<A,Two>::type, typename divides<typename minus<A,One>::type,Two>::type >::type type;};template<class A, class B>struct times { struct _Expr1 { typedef typename negate<typename times<A,typename negate<B>::type>::type>::type type; }; struct _Expr2 { typedef typename plus<A,typename times<A,typename minus<B,One>::type>::type>::type type; }; struct _Expr3 { typedef typename times<typename plus<A,A>::type,typename divides<B,Two>::type>::type type; }; typedef typename cond< equal_to<B,Zero>, spawn<A,0>, equal_to<B,One>, identity<A>, less<B,Zero>, _Expr1, isOdd<B>, _Expr2, _Expr3 >::type type;};
template<class A, class B>struct modulus { typedef typename minus<A,typename times<typename divides<A,B>::type,B>::type>::type type;};template<class T>struct print { typedef T type;};
template<typename... Args>struct list { typedef list<Args...> type; typedef tuple<Args...> ttype; // 为了打印 static const std::size_t size = sizeof...(Args); //为了打印};template<std::size_t i, typename TT>struct loop_list{ static void run() { cout << std::boolalpha; cout << std::tuple_element<i, TT>::type::value << endl; loop_list<i-1, TT>::run(); }};template<typename TT>struct loop_list<0, TT>{ static void run() {cout << std::tuple_element<0, TT>::type::value << endl;}};template<typename LL>void pl(){ typedef typename LL::ttype TT; loop_list<LL::size-1, TT>::run();}template<typename,typename>struct cons;template<typename x,typename... y>struct cons<x,list<y...> >{ typedef typename list<x,y...>::type type;};template<typename,typename...>struct map;template<typename f>struct map<f>{ typedef typename list<>::type type;};template<typename car,typename... cdr,typename f>struct map<f,car,cdr...>{ typedef typename cons<typename f::template apply<car>::type, typename map<f,cdr...>::type>::type type;};struct M_isOdd { struct M { template<typename x> struct apply { typedef typename ::not_equal_to< typename ::modulus<x,::PInt<2> >::type, ::PInt<0> >::type type; }; }; typedef M type;};typedef ::print< map<M_isOdd::type, ::PInt<1>, ::PInt<2>, ::PInt<3>, ::PInt<4>, ::PInt<5>, ::PInt<6>, ::PInt<7>, ::PInt<8>, ::PInt<9> >::type >::type M8;int main(){ pl<M8>(); return 0;}
完毕, 以后又机会再深入分享。。。
- 用Cpp11新template feature尝试metaprogramming
- Template Metaprogramming
- template metaprogramming
- Functional Programming & Template Metaprogramming
- CppCon - Modern Template Metaprogramming 杂记
- cpp11新特性详解与应用
- 自己的一个MP(MetaProgramming)尝试
- C++ template metaprogramming学习笔记一
- 从今天开始翻译 C++ Template Metaprogramming
- 《C++ Template Metaprogramming》习题3-0
- 《C++ Template Metaprogramming》译序——经典之后的经典
- 《C++ Template Metaprogramming》附录A——预处理元编程
- Template Metaprogramming
- 《C++ Template Metaprogramming》附录A——预处理元编程
- 《C++ Template Metaprogramming》译序——经典之后的经典
- Template Metaprogramming
- 《C++ Template Metaprogramming》附录A——预处理元编程
- 《C++ Template Metaprogramming》译序——经典之后的经典
- 利用db2联邦数据库轻松实现程序部署
- 一个自动化任务抽象类
- Cannot modify header information - headers already sent by ...
- VC获取操作系统版本信息
- 仆人式管理风格
- 用Cpp11新template feature尝试metaprogramming
- 九度1006
- Task: 最简洁的iPhone任务管理App
- 关于函数在.c文件定义在.h文件声明与makefile
- 在上传图片前实现图片预览
- iOS-上传应用程序到app store
- Mysql的锁机制
- LR支持的脚本语言
- ORACLE安装报错求助