Last active
February 19, 2020 16:36
-
-
Save notfoundry/9ec3ebf9f6ffbc56505202226ec93359 to your computer and use it in GitHub Desktop.
Type-level lambda expressions for template metaprogramming in C++20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <boost/preprocessor/punctuation/is_begin_parens.hpp> | |
| #include <boost/preprocessor/punctuation/remove_parens.hpp> | |
| #include <boost/preprocessor/control/if.hpp> | |
| #include <boost/preprocessor/seq/for_each.hpp> | |
| #include <boost/preprocessor/seq/variadic_seq_to_seq.hpp> | |
| namespace metalambda { | |
| template <auto T> | |
| struct template_funcall_adapter { | |
| template <class... Ts> | |
| using f = decltype(T.template operator()<Ts...>()); | |
| }; | |
| } | |
| #define METALAMBDA_RETURN(...) return __VA_ARGS__(); }> | |
| #define METALAMBDA_RETURN_THUNK METALAMBDA_RETURN | |
| #define METALAMBDA_GENERATE_LOCAL(r, data, elem) using BOOST_PP_REMOVE_PARENS(elem); | |
| #define METALAMBDA_LOCALS(seq) BOOST_PP_SEQ_FOR_EACH(METALAMBDA_GENERATE_LOCAL, _, BOOST_PP_VARIADIC_SEQ_TO_SEQ(seq)) METALAMBDA_RETURN | |
| #define METALAMBDA_DISPATCH_LOCALS_OR_PARAMS_IMPL(continuation, ...) continuation(__VA_ARGS__) | |
| #define METALAMBDA_DISPATCH_LOCALS_OR_PARAMS(...) METALAMBDA_DISPATCH_LOCALS_OR_PARAMS_IMPL(BOOST_PP_IF(BOOST_PP_IS_BEGIN_PARENS(__VA_ARGS__), METALAMBDA_LOCALS, METALAMBDA_RETURN_THUNK), __VA_ARGS__) | |
| #define METALAMBDA_PARAMS(...) ::metalambda::template_funcall_adapter<[]<__VA_ARGS__>(){ METALAMBDA_DISPATCH_LOCALS_OR_PARAMS | |
| #define METALAMBDA(...) METALAMBDA_PARAMS(__VA_ARGS__) | |
| #define II(...) METALAMBDA(__VA_ARGS__) | |
| #define METALAMBDA_RETURN_AND_EVAL(...) return __VA_ARGS__(); }>::template f<> | |
| #define LET(...) typename BOOST_PP_CAT(METALAMBDA(class = void)(__VA_ARGS__), _AND_EVAL) | |
| #include <kvasir/mpl/mpl.hpp> | |
| using size_lt = II(class T1, class T2)(kvasir::mpl::bool_<sizeof(T1) < sizeof(T2)>); | |
| using int_long_list = | |
| LET((x = int)(y = long)) | |
| (kvasir::mpl::list<x, y>); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment