Skip to content

Instantly share code, notes, and snippets.

@argv0
Created June 2, 2011 22:23
Show Gist options
  • Save argv0/1005466 to your computer and use it in GitHub Desktop.
Save argv0/1005466 to your computer and use it in GitHub Desktop.
compile time typelists and fold metafunction
#include <stdio.h>
/* an empty type to mark the empty list */
struct null_typelist {};
/* list representation */
template <class H, class T>
struct typelist {
typedef typelist<H, T> type;
typedef H head;
typedef T tail;
};
/* constructor for typelists of length 0-4 */
template <
class T1=null_typelist, class T2=null_typelist,
class T3=null_typelist, class T4=null_typelist
>
struct make_typelist {
private:
// tail
typedef typename make_typelist<T2,T3,T4>::type tail_type;
public:
// cons [H|T]
typedef typelist<T1, tail_type> type;
};
/* specialization to stop recursion */
template <>
struct make_typelist<> {
typedef null_typelist type;
};
/* simple helper class that creates unique types from integer constants */
template <int i>
struct int2type {
typedef int2type<i> type;
static const int value = i;
};
/* some int-typedefs */
typedef int2type<0> zero;
typedef int2type<1> one;
typedef int2type<2> two;
typedef int2type<3> three;
typedef int2type<4> four;
/* has inner "apply" metafunction that "returns" the result
of adding two int2types */
struct adder {
template <class Elem, class Acc>
struct apply {
typedef int2type<Elem::value + Acc::value> type;
};
};
/* foldl implementation */
template <class L, class Fun, class Accin>
struct foldl;
/* primary template : foldl(List, Fun, Accin */
template <class L, class Fun, class Accin>
struct foldl {
/* call Fun(H, AccIn) -> NewAcc */
typedef typename Fun::template apply<typename L::head, Accin>::type NewAcc;
/* foldl(Tail, Fun, NewAcc) */
typedef typename foldl<typename L::tail, Fun, NewAcc>::type type;
};
/* specialization to stop fold */
template <class Fun, class Accin>
struct foldl<null_typelist, Fun, Accin> {
typedef typename Accin::type type;
};
int main(int argc, char **argv) {
typedef make_typelist<one, two, three, four>::type mylist;
typedef foldl<mylist, adder, zero>::type folder;
printf("%d\n", folder::value);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment