Skip to content

Instantly share code, notes, and snippets.

@andik
Created March 18, 2015 22:17
Show Gist options
  • Save andik/da76a26b8056b56700ee to your computer and use it in GitHub Desktop.
Save andik/da76a26b8056b56700ee to your computer and use it in GitHub Desktop.
C++ PP List and PP Typelists
#define List(o) \
o(1,2) \
o(2,3) \
#define MAP_CALL_FN_PARENS(...) (__VA_ARGS__);
#define MAP_CALL_FN(fn) fn MAP_CALL_FN_PARENS
#define MAP(list, fn, ...) list(MAP_CALL_FN(fn))
#define elem(...) element __VA_ARGS__
#define NONE
List(elem)
MAP(List, myfn)
// Works due to
List(xy elem)
// is xy elem(1,2) xy elem(3,4)
#define CASE_RETURN(a,b) case a: return b;
#define LIST_AS_ARRAY(...) {__VA_ARGS__},
#define Typelist(__firs, __elem, __last) \
__firs(int, mya, 0) \
__elem(int, myb, 1) \
__elem(int, myc, 2) \
__elem(int, myd, 3) \
__last(int, mye, 4) \
List(CASE_RETURN)
myArray = {
List(LIST_AS_ARRAY)
};
#define PROTO_FOR_TYPELIST_EL(type, name, value) type name,
#define PROTO_FOR_TYPELIST_E(type, name, value) type name
#define PROTO_FOR_TYPELIST(RetType, name, Typelist) \
RetType name(Typelist(PROTO_FOR_TYPELIST_EL, PROTO_FOR_TYPELIST_EL, PROTO_FOR_TYPELIST_E))
#define CALL_WITH_TYPELIST_EL(type, name, value) name,
#define CALL_WITH_TYPELIST_E(type, name, value) name
#define CALL_WITH_TYPELIST(name, Typelist) \
name(Typelist(CALL_WITH_TYPELIST_EL, CALL_WITH_TYPELIST_EL, CALL_WITH_TYPELIST_E))
#define INIT_FOR_TYPELIST_A(t, name, val) : name(val)
#define INIT_FOR_TYPELIST_EL(t, name, val) , name(val)
#define INIT_FOR_TYPELIST(Typelist) \
Typelist(INIT_FOR_TYPELIST_A, INIT_FOR_TYPELIST_EL, INIT_FOR_TYPELIST_EL)
#define DECL_FOR_TYPELIST_EL(t, name, val) t name;
#define DECL_FOR_TYPELIST(Typelist) \
Typelist(DECL_FOR_TYPELIST_EL, DECL_FOR_TYPELIST_EL, DECL_FOR_TYPELIST_EL)
#define LAMBDA_INIT_FOR_TYPELIST_A(t, name, val) : name(arg_##name)
#define LAMBDA_INIT_FOR_TYPELIST_EL(t, name, val) , name(arg_##name)
#define LAMBDA_INIT_FOR_TYPELIST(Typelist) \
Typelist(LAMBDA_INIT_FOR_TYPELIST_A, LAMBDA_INIT_FOR_TYPELIST_EL, LAMBDA_INIT_FOR_TYPELIST_EL)
#define LAMBDA_CONPROTO_FOR_TYPELIST_EL(type, name, value) type arg_##name,
#define LAMBDA_CONPROTO_FOR_TYPELIST_E(type, name, value) type arg_##name
#define LAMBDA_CONPROTO_FOR_TYPELIST(RetType, name, Typelist) \
RetType name(Typelist(LAMBDA_CONPROTO_FOR_TYPELIST_EL, LAMBDA_CONPROTO_FOR_TYPELIST_EL, LAMBDA_CONPROTO_FOR_TYPELIST_E))
#define LAMBDA_FOR_TYPELIST(RetType, name, Typelist, code, ...) \
class name##Class { \
public: \
LAMBDA_CONPROTO_FOR_TYPELIST(NONE, name##Class, Typelist) \
LAMBDA_INIT_FOR_TYPELIST(Typelist) {} \
\
RetType operator()(__VA_ARGS__) { code } \
private: \
DECL_FOR_TYPELIST(Typelist) \
}; \
CALL_WITH_TYPELIST(name##Class, Typelist); \
PROTO_FOR_TYPELIST(int, myfun, Typelist)
INIT_FOR_TYPELIST(Typelist)
LAMBDA_FOR_TYPELIST(int, mylambda, Typelist, { return 1 +2 })
// Practical Lambda
#define capture(A,O,E) \
A(int, a, 0) \
E(int, b, 0) \
LAMBDA_FOR_TYPELIST(int, aTestLambda, capture, { return a+b+c }, int c)
// anonymous function
#define ANON(name, code) \
class name##Class { \
public: \
RetType operator()(__VA_ARGS__) { code } \
}; \
name##Class name; \
ANON(anonymous, {return 3+4;})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment