File indexing completed on 2026-08-17 08:52:05
0001
0002
0003
0004
0005
0006 #ifndef BOOST_OPENMETHOD_MACROS_HPP
0007 #define BOOST_OPENMETHOD_MACROS_HPP
0008
0009 #include <boost/preprocessor/cat.hpp>
0010
0011 #include <boost/openmethod/core.hpp>
0012
0013 namespace boost::openmethod::detail {
0014
0015 template<typename, class Method, typename ReturnType, typename... Parameters>
0016 struct enable_forwarder;
0017
0018 template<class Method, typename ReturnType, typename... Parameters>
0019 struct enable_forwarder<
0020 std::void_t<decltype(Method::fn(std::declval<Parameters>()...))>, Method,
0021 ReturnType, Parameters...> {
0022 using type = ReturnType;
0023 };
0024
0025 template<class...>
0026 struct va_args;
0027
0028 template<class ReturnType, class Registry>
0029 struct va_args<ReturnType, Registry> {
0030 using return_type = ReturnType;
0031 using registry = Registry;
0032 };
0033
0034 template<class ReturnType>
0035 struct va_args<ReturnType> {
0036 using return_type = ReturnType;
0037 using registry = macro_default_registry;
0038 };
0039
0040 }
0041
0042 #define BOOST_OPENMETHOD_GENSYM BOOST_PP_CAT(openmethod_gensym_, __COUNTER__)
0043
0044 #define BOOST_OPENMETHOD_REGISTER(...) \
0045 static __VA_ARGS__ BOOST_OPENMETHOD_GENSYM
0046
0047 #define BOOST_OPENMETHOD_ID(NAME) NAME##_boost_openmethod
0048
0049 #define BOOST_OPENMETHOD_OVERRIDERS(NAME) \
0050 BOOST_PP_CAT(BOOST_OPENMETHOD_ID(NAME), _overriders)
0051
0052 #define BOOST_OPENMETHOD_OVERRIDER(NAME, ARGS, ...) \
0053 BOOST_OPENMETHOD_OVERRIDERS(NAME)<__VA_ARGS__ ARGS>
0054
0055 #define BOOST_OPENMETHOD_GUIDE(NAME) \
0056 BOOST_PP_CAT(BOOST_OPENMETHOD_ID(NAME), _guide)
0057
0058 #define BOOST_OPENMETHOD_TYPE(NAME, ARGS, ...) \
0059 ::boost::openmethod::method< \
0060 BOOST_OPENMETHOD_ID(NAME), \
0061 ::boost::openmethod::detail::va_args<__VA_ARGS__>::return_type ARGS, \
0062 ::boost::openmethod::detail::va_args<__VA_ARGS__>::registry>
0063
0064 #define BOOST_OPENMETHOD(NAME, ARGS, ...) \
0065 template<typename...> \
0066 struct BOOST_OPENMETHOD_OVERRIDERS(NAME); \
0067 struct BOOST_OPENMETHOD_ID(NAME); \
0068 template<typename... ForwarderParameters> \
0069 typename ::boost::openmethod::detail::enable_forwarder< \
0070 void, BOOST_OPENMETHOD_TYPE(NAME, ARGS, __VA_ARGS__), \
0071 typename BOOST_OPENMETHOD_TYPE(NAME, ARGS, __VA_ARGS__), \
0072 ForwarderParameters...>::type \
0073 BOOST_OPENMETHOD_GUIDE(NAME)(ForwarderParameters && ... args); \
0074 template<typename... ForwarderParameters> \
0075 inline auto NAME(ForwarderParameters&&... args) -> \
0076 typename ::boost::openmethod::detail::enable_forwarder< \
0077 void, BOOST_OPENMETHOD_TYPE(NAME, ARGS, __VA_ARGS__), \
0078 ::boost::openmethod::detail::va_args<__VA_ARGS__>::return_type, \
0079 ForwarderParameters...>::type { \
0080 return BOOST_OPENMETHOD_TYPE(NAME, ARGS, __VA_ARGS__)::fn( \
0081 std::forward<ForwarderParameters>(args)...); \
0082 }
0083
0084 #define BOOST_OPENMETHOD_DETAIL_LOCATE_METHOD(NAME, ARGS) \
0085 template<typename T> \
0086 struct boost_openmethod_detail_locate_method_aux; \
0087 template<typename... A> \
0088 struct boost_openmethod_detail_locate_method_aux<void(A...)> { \
0089 using type = \
0090 decltype(BOOST_OPENMETHOD_GUIDE(NAME)(std::declval<A>()...)); \
0091 };
0092
0093 #define BOOST_OPENMETHOD_DECLARE_OVERRIDER(NAME, ARGS, ...) \
0094 template<typename...> \
0095 struct BOOST_OPENMETHOD_OVERRIDERS(NAME); \
0096 template<> \
0097 struct BOOST_OPENMETHOD_OVERRIDERS(NAME)<__VA_ARGS__ ARGS> { \
0098 BOOST_OPENMETHOD_DETAIL_LOCATE_METHOD(NAME, ARGS); \
0099 static auto fn ARGS->__VA_ARGS__; \
0100 static auto has_next() -> bool; \
0101 template<typename... Args> \
0102 static auto next(Args&&... args) -> decltype(auto); \
0103 }; \
0104 inline auto BOOST_OPENMETHOD_OVERRIDERS( \
0105 NAME)<__VA_ARGS__ ARGS>::has_next() -> bool { \
0106 return boost_openmethod_detail_locate_method_aux< \
0107 void ARGS>::type::has_next<fn>(); \
0108 } \
0109 template<typename... Args> \
0110 inline auto BOOST_OPENMETHOD_OVERRIDERS(NAME)<__VA_ARGS__ ARGS>::next( \
0111 Args&&... args) -> decltype(auto) { \
0112 return boost_openmethod_detail_locate_method_aux< \
0113 void ARGS>::type::next<fn>(std::forward<Args>(args)...); \
0114 }
0115
0116 #define BOOST_OPENMETHOD_DETAIL_REGISTER_OVERRIDER(NAME, ARGS, ...) \
0117 BOOST_OPENMETHOD_REGISTER( \
0118 BOOST_OPENMETHOD_OVERRIDERS(NAME) < __VA_ARGS__ ARGS > \
0119 ::boost_openmethod_detail_locate_method_aux<void ARGS>::type:: \
0120 override< \
0121 BOOST_OPENMETHOD_OVERRIDERS(NAME) < __VA_ARGS__ ARGS>::fn >);
0122
0123 #define BOOST_OPENMETHOD_DEFINE_OVERRIDER(NAME, ARGS, ...) \
0124 BOOST_OPENMETHOD_DETAIL_REGISTER_OVERRIDER(NAME, ARGS, __VA_ARGS__) \
0125 auto BOOST_OPENMETHOD_OVERRIDER(NAME, ARGS, __VA_ARGS__)::fn ARGS \
0126 -> boost::mp11::mp_back<boost::mp11::mp_list<__VA_ARGS__>>
0127
0128 #define BOOST_OPENMETHOD_OVERRIDE(NAME, ARGS, ...) \
0129 BOOST_OPENMETHOD_DECLARE_OVERRIDER(NAME, ARGS, __VA_ARGS__) \
0130 BOOST_OPENMETHOD_DEFINE_OVERRIDER(NAME, ARGS, __VA_ARGS__)
0131
0132 #define BOOST_OPENMETHOD_INLINE_OVERRIDE(NAME, ARGS, ...) \
0133 BOOST_OPENMETHOD_DECLARE_OVERRIDER(NAME, ARGS, __VA_ARGS__) \
0134 BOOST_OPENMETHOD_DETAIL_REGISTER_OVERRIDER(NAME, ARGS, __VA_ARGS__) \
0135 inline auto BOOST_OPENMETHOD_OVERRIDER(NAME, ARGS, __VA_ARGS__)::fn ARGS \
0136 -> boost::mp11::mp_back<boost::mp11::mp_list<__VA_ARGS__>>
0137
0138 #define BOOST_OPENMETHOD_CLASSES(...) \
0139 BOOST_OPENMETHOD_REGISTER(::boost::openmethod::use_classes<__VA_ARGS__>);
0140
0141 #endif