Skip to content

Instantly share code, notes, and snippets.

@seanchas116
Last active December 23, 2015 03:59
Show Gist options
  • Save seanchas116/6577153 to your computer and use it in GitHub Desktop.
Save seanchas116/6577153 to your computer and use it in GitHub Desktop.
A set of C++ macros for defining extension methods
#include <vector>
#include <iostream>
#include <type_traits>
#include <boost/preprocessor.hpp>
#define GET_TYPE(n, array) \
BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_ARRAY_ELEM(n, array))
#define GET_ARG(n, array) \
BOOST_PP_TUPLE_ELEM(2, 1, BOOST_PP_ARRAY_ELEM(n, array))
#define ARG_LIST_REPEATER(z, n, array) \
BOOST_PP_COMMA_IF(n) GET_TYPE(n, array) GET_ARG(n, array)
#define ARG_DEFS_REPEATER(z, n, array) \
GET_TYPE(n, array) GET_ARG(n, array);
#define ARG_INITS_REPEATER(z, n, array) \
BOOST_PP_COMMA_IF(n) GET_ARG(n, array)(GET_ARG(n, array))
#define ARG_CALL_REPEATER(z, n, array) \
BOOST_PP_COMMA_IF(n) GET_ARG(n, array)
#define ARRAY_REPEAT(array, macro) \
BOOST_PP_REPEAT(BOOST_PP_ARRAY_SIZE(array), macro, array)
#define ARG_LIST(array) \
ARRAY_REPEAT(array, ARG_LIST_REPEATER)
#define ARG_DEFS(array) \
ARRAY_REPEAT(array, ARG_DEFS_REPEATER)
#define ARG_INITS(array) \
ARRAY_REPEAT(array, ARG_INITS_REPEATER)
#define ARG_CALL(array) \
ARRAY_REPEAT(array, ARG_CALL_REPEATER)
#define METHOD(NAME, TYPE_ARG_ARRAY, ...) \
namespace detail { \
struct NAME##_args { \
NAME##_args(ARG_LIST(TYPE_ARG_ARRAY)) \
BOOST_PP_IF(BOOST_PP_ARRAY_SIZE(TYPE_ARG_ARRAY), : , ) \
ARG_INITS(TYPE_ARG_ARRAY) \
{} \
ARG_DEFS(TYPE_ARG_ARRAY) \
__VA_ARGS__ \
}; \
} \
detail::NAME##_args NAME(ARG_LIST(TYPE_ARG_ARRAY)) { \
return detail::NAME##_args(ARG_CALL(TYPE_ARG_ARRAY)); \
} \
template <typename T> \
auto operator|(T &self, detail::NAME##_args &&args) -> decltype(args.apply_(self)) { \
return args.apply_(self); \
}
#define METHOD0(NAME, ...) \
METHOD(NAME, (0, ()), __VA_ARGS__)
#define METHOD1(NAME, T0, A0, ...) \
METHOD(NAME, (1, ((T0, A0))), __VA_ARGS__)
#define METHOD2(NAME, T0, A0, T1, A1, ...) \
METHOD(NAME, (2, ((T0, A0), (T1, A1))), __VA_ARGS__)
#define METHOD3(NAME, T0, A0, T1, A1, T2, A2, ...) \
METHOD(NAME, (3, ((T0, A0), (T1, A1), (T2, A2))), __VA_ARGS__)
#define METHOD4(NAME, T0, A0, T1, A1, T2, A2, T3, A3, ...) \
METHOD(NAME, (4, ((T0, A0), (T1, A1), (T2, A2), (T3, A3))), __VA_ARGS__)
#define METHOD5(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, ...) \
METHOD(NAME, (5, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4))), __VA_ARGS__)
#define METHOD6(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, ...) \
METHOD(NAME, (6, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5))), __VA_ARGS__)
#define METHOD7(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, ...) \
METHOD(NAME, (7, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6))), __VA_ARGS__)
#define METHOD8(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, ...) \
METHOD(NAME, (8, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7))), __VA_ARGS__)
#define METHOD9(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, ...) \
METHOD(NAME, (9, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8))), __VA_ARGS__)
#define METHOD10(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, ...) \
METHOD(NAME, (10, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9))), __VA_ARGS__)
#define METHOD11(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, ...) \
METHOD(NAME, (11, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10))), __VA_ARGS__)
#define METHOD12(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, T11, A11, ...) \
METHOD(NAME, (12, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10), (T11, A11))), __VA_ARGS__)
#define METHOD13(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, T11, A11, T12, A12, ...) \
METHOD(NAME, (13, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10), (T11, A11), (T12, A12))), __VA_ARGS__)
#define METHOD14(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, T11, A11, T12, A12, T13, A13, ...) \
METHOD(NAME, (14, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10), (T11, A11), (T12, A12), (T13, A13))), __VA_ARGS__)
#define METHOD15(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, T11, A11, T12, A12, T13, A13, T14, A14, ...) \
METHOD(NAME, (15, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10), (T11, A11), (T12, A12), (T13, A13), (T14, A14))), __VA_ARGS__)
#define METHOD16(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, T11, A11, T12, A12, T13, A13, T14, A14, T15, A15, ...) \
METHOD(NAME, (16, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10), (T11, A11), (T12, A12), (T13, A13), (T14, A14), (T15, A15))), __VA_ARGS__)
#define METHOD17(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, T11, A11, T12, A12, T13, A13, T14, A14, T15, A15, T16, A16, ...) \
METHOD(NAME, (17, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10), (T11, A11), (T12, A12), (T13, A13), (T14, A14), (T15, A15), (T16, A16))), __VA_ARGS__)
#define METHOD18(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, T11, A11, T12, A12, T13, A13, T14, A14, T15, A15, T16, A16, T17, A17, ...) \
METHOD(NAME, (18, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10), (T11, A11), (T12, A12), (T13, A13), (T14, A14), (T15, A15), (T16, A16), (T17, A17))), __VA_ARGS__)
#define METHOD19(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, T11, A11, T12, A12, T13, A13, T14, A14, T15, A15, T16, A16, T17, A17, T18, A18, ...) \
METHOD(NAME, (19, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10), (T11, A11), (T12, A12), (T13, A13), (T14, A14), (T15, A15), (T16, A16), (T17, A17), (T18, A18))), __VA_ARGS__)
#define METHOD20(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, T11, A11, T12, A12, T13, A13, T14, A14, T15, A15, T16, A16, T17, A17, T18, A18, T19, A19, ...) \
METHOD(NAME, (20, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10), (T11, A11), (T12, A12), (T13, A13), (T14, A14), (T15, A15), (T16, A16), (T17, A17), (T18, A18), (T19, A19))), __VA_ARGS__)
#define METHOD21(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, T11, A11, T12, A12, T13, A13, T14, A14, T15, A15, T16, A16, T17, A17, T18, A18, T19, A19, T20, A20, ...) \
METHOD(NAME, (21, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10), (T11, A11), (T12, A12), (T13, A13), (T14, A14), (T15, A15), (T16, A16), (T17, A17), (T18, A18), (T19, A19), (T20, A20))), __VA_ARGS__)
#define METHOD22(NAME, T0, A0, T1, A1, T2, A2, T3, A3, T4, A4, T5, A5, T6, A6, T7, A7, T8, A8, T9, A9, T10, A10, T11, A11, T12, A12, T13, A13, T14, A14, T15, A15, T16, A16, T17, A17, T18, A18, T19, A19, T20, A20, T21, A21, ...) \
METHOD(NAME, (22, ((T0, A0), (T1, A1), (T2, A2), (T3, A3), (T4, A4), (T5, A5), (T6, A6), (T7, A7), (T8, A8), (T9, A9), (T10, A10), (T11, A11), (T12, A12), (T13, A13), (T14, A14), (T15, A15), (T16, A16), (T17, A17), (T18, A18), (T19, A19), (T20, A20), (T21, A21))), __VA_ARGS__)
METHOD2(sliced, size_t, start, size_t, length,
template <typename T>
T apply_(T &self)
{
T ret(length);
std::copy(self.begin() + start, self.begin() + start + length, ret.begin());
return ret;
}
)
METHOD1(at, size_t, index,
template <typename T>
auto apply_(T &self) -> decltype(self.at(index))
{
return self.at(index);
}
)
METHOD0(size,
template <typename T>
auto apply_(T &self) -> decltype(self.size())
{
return self.size();
}
)
int main()
{
std::vector<double> xs = {1.0, 1.5, 2.0};
const auto &const_xs = xs;
std::cout << (xs | size()) << std::endl;
std::cout << (const_xs | at(1)) << std::endl;
std::cout << (xs | at(1)) << std::endl;
auto sub = xs | sliced(0, 2);
for (auto x : sub)
std::cout << x << " ";
std::cout << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment