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 solution
template<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;
}
完毕, 以后又机会再深入分享。。。