Skip to content

Instantly share code, notes, and snippets.

@ddemidov
Last active August 29, 2015 13:57
Show Gist options
  • Save ddemidov/9891163 to your computer and use it in GitHub Desktop.
Save ddemidov/9891163 to your computer and use it in GitHub Desktop.
Boost.PP parse parameter list
run:
@g++ -E pp.cpp | tail -n 1 | clang-format | pygmentize -l cpp
check:
@g++ -E pp.cpp
#define BOOST_PP_VARIADICS 1
#include <boost/preprocessor/enum.hpp>
#include <boost/preprocessor/enum_params.hpp>
#include <boost/preprocessor/seq.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/tuple.hpp>
#include <boost/preprocessor/stringize.hpp>
#define VEXCL_FUNCTION_PRINT_ARG_REF(z, n, data) const Arg##n &
#define VEXCL_FUNCTION_PRINT_PARAM(z, n, data) const Arg##n &arg##n
#define VEXCL_FUNCTION_PRINT_BOOST_REF(z, n, data) boost::ref(arg##n)
#define VEXCL_FUNCTION_ARG_TYPE(n, args) \
BOOST_PP_TUPLE_ELEM(0, BOOST_PP_SEQ_ELEM(n, args))
#define VEXCL_FUNCTION_ARG_NAME(n, args) \
BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(1, BOOST_PP_SEQ_ELEM(n, args)))
#define VEXCL_FUNCTION_DEF_ARG(z, n, args) \
src.parameter<VEXCL_FUNCTION_ARG_TYPE(n, args)>( \
VEXCL_FUNCTION_ARG_NAME(n, args));
#define VEXCL_FUNCTION_DEFINE_DEP(z, data, dep) dep.define(src);
#define VEX_FUNCTION_SINK(type, func_name, nargs, args, deps, body) \
struct vex_function_##func_name : vex::user_function { \
typedef type value_type; \
vex_function_##func_name() {} \
template <BOOST_PP_ENUM_PARAMS(nargs, class Arg)> \
typename boost::proto::result_of::make_expr< \
boost::proto::tag::function, vex_function_##func_name, \
BOOST_PP_ENUM(nargs, VEXCL_FUNCTION_PRINT_ARG_REF, ~) \
>::type const \
operator()( BOOST_PP_ENUM(nargs, VEXCL_FUNCTION_PRINT_PARAM, ~) ) const { \
return boost::proto::make_expr<boost::proto::tag::function>( \
vex_function_##func_name, \
BOOST_PP_ENUM(nargs, VEXCL_FUNCTION_PRINT_BOOST_REF, ~) \
); \
} \
static std::string name() { return #func_name; } \
static void define(vex::backend::source_generator &src) { \
define( src, name() ); \
} \
static void define(vex::backend::source_generator &src, \
const std::string &fname) \
{ \
BOOST_PP_SEQ_FOR_EACH(VEXCL_FUNCTION_DEFINE_DEP, ~, deps) \
src.function< type >(fname).open("("); \
BOOST_PP_REPEAT(nargs, VEXCL_FUNCTION_DEF_ARG, args) \
src.close(")").open("{").new_line() << body; \
src.close("}"); \
} \
} const func_name
#define VEXCL_FUNCTION_MAKE_SEQ_0(...) ((__VA_ARGS__)) VEXCL_FUNCTION_MAKE_SEQ_1
#define VEXCL_FUNCTION_MAKE_SEQ_1(...) ((__VA_ARGS__)) VEXCL_FUNCTION_MAKE_SEQ_0
#define VEXCL_FUNCTION_MAKE_SEQ_0_END
#define VEXCL_FUNCTION_MAKE_SEQ_1_END
#define VEXCL_FUNCTION_MAKE_SEQ(args) \
BOOST_PP_CAT(VEXCL_FUNCTION_MAKE_SEQ_0 args,_END)
#define VEX_FUNCTION_SD(type, name, args, deps, body) \
VEX_FUNCTION_SINK(type, name, \
BOOST_PP_SEQ_SIZE(VEXCL_FUNCTION_MAKE_SEQ(args)), \
VEXCL_FUNCTION_MAKE_SEQ(args), deps, body)
#define VEX_FUNCTION_DS VEX_FUNCTION_SD
#define VEX_FUNCTION_S(type, name, args, body) \
VEX_FUNCTION_SD(type, name, args, , body)
#define VEX_FUNCTION_D(type, name, args, deps, ...) \
VEX_FUNCTION_SD(type, name, args, deps, BOOST_PP_STRINGIZE(__VA_ARGS__) )
#define VEX_FUNCTION(type, name, args, ...) \
VEX_FUNCTION_S(type, name, args, BOOST_PP_STRINGIZE(__VA_ARGS__))
VEX_FUNCTION_D(int, append, (double, a)(const char *, b), (sum)(min), return a + b;);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment