macros.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Copyright (c) 2018-2025 Jean-Louis Leroy
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // See accompanying file LICENSE_1_0.txt
  4. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_OPENMETHOD_MACROS_HPP
  6. #define BOOST_OPENMETHOD_MACROS_HPP
  7. #include <boost/preprocessor/cat.hpp>
  8. #include <boost/openmethod/core.hpp>
  9. namespace boost::openmethod::detail {
  10. template<typename, class Method, typename ReturnType, typename... Parameters>
  11. struct enable_forwarder;
  12. template<class Method, typename ReturnType, typename... Parameters>
  13. struct enable_forwarder<
  14. std::void_t<decltype(Method::fn(std::declval<Parameters>()...))>, Method,
  15. ReturnType, Parameters...> {
  16. using type = ReturnType;
  17. };
  18. template<class...>
  19. struct va_args;
  20. template<class ReturnType, class Registry>
  21. struct va_args<ReturnType, Registry> {
  22. using return_type = ReturnType;
  23. using registry = Registry;
  24. };
  25. template<class ReturnType>
  26. struct va_args<ReturnType> {
  27. using return_type = ReturnType;
  28. using registry = macro_default_registry;
  29. };
  30. } // namespace boost::openmethod::detail
  31. #define BOOST_OPENMETHOD_GENSYM BOOST_PP_CAT(openmethod_gensym_, __COUNTER__)
  32. #define BOOST_OPENMETHOD_REGISTER(...) \
  33. static __VA_ARGS__ BOOST_OPENMETHOD_GENSYM
  34. #define BOOST_OPENMETHOD_ID(NAME) NAME##_boost_openmethod
  35. #define BOOST_OPENMETHOD_OVERRIDERS(NAME) \
  36. BOOST_PP_CAT(BOOST_OPENMETHOD_ID(NAME), _overriders)
  37. #define BOOST_OPENMETHOD_OVERRIDER(NAME, ARGS, ...) \
  38. BOOST_OPENMETHOD_OVERRIDERS(NAME)<__VA_ARGS__ ARGS>
  39. #define BOOST_OPENMETHOD_GUIDE(NAME) \
  40. BOOST_PP_CAT(BOOST_OPENMETHOD_ID(NAME), _guide)
  41. #define BOOST_OPENMETHOD_TYPE(NAME, ARGS, ...) \
  42. ::boost::openmethod::method< \
  43. BOOST_OPENMETHOD_ID(NAME), \
  44. ::boost::openmethod::detail::va_args<__VA_ARGS__>::return_type ARGS, \
  45. ::boost::openmethod::detail::va_args<__VA_ARGS__>::registry>
  46. #define BOOST_OPENMETHOD(NAME, ARGS, ...) \
  47. template<typename...> \
  48. struct BOOST_OPENMETHOD_OVERRIDERS(NAME); \
  49. struct BOOST_OPENMETHOD_ID(NAME); \
  50. template<typename... ForwarderParameters> \
  51. typename ::boost::openmethod::detail::enable_forwarder< \
  52. void, BOOST_OPENMETHOD_TYPE(NAME, ARGS, __VA_ARGS__), \
  53. typename BOOST_OPENMETHOD_TYPE(NAME, ARGS, __VA_ARGS__), \
  54. ForwarderParameters...>::type \
  55. BOOST_OPENMETHOD_GUIDE(NAME)(ForwarderParameters && ... args); \
  56. template<typename... ForwarderParameters> \
  57. inline auto NAME(ForwarderParameters&&... args) -> \
  58. typename ::boost::openmethod::detail::enable_forwarder< \
  59. void, BOOST_OPENMETHOD_TYPE(NAME, ARGS, __VA_ARGS__), \
  60. ::boost::openmethod::detail::va_args<__VA_ARGS__>::return_type, \
  61. ForwarderParameters...>::type { \
  62. return BOOST_OPENMETHOD_TYPE(NAME, ARGS, __VA_ARGS__)::fn( \
  63. std::forward<ForwarderParameters>(args)...); \
  64. }
  65. #define BOOST_OPENMETHOD_DETAIL_LOCATE_METHOD(NAME, ARGS) \
  66. template<typename T> \
  67. struct boost_openmethod_detail_locate_method_aux; \
  68. template<typename... A> \
  69. struct boost_openmethod_detail_locate_method_aux<void(A...)> { \
  70. using type = \
  71. decltype(BOOST_OPENMETHOD_GUIDE(NAME)(std::declval<A>()...)); \
  72. };
  73. #define BOOST_OPENMETHOD_DECLARE_OVERRIDER(NAME, ARGS, ...) \
  74. template<typename...> \
  75. struct BOOST_OPENMETHOD_OVERRIDERS(NAME); \
  76. template<> \
  77. struct BOOST_OPENMETHOD_OVERRIDERS(NAME)<__VA_ARGS__ ARGS> { \
  78. BOOST_OPENMETHOD_DETAIL_LOCATE_METHOD(NAME, ARGS); \
  79. static auto fn ARGS->__VA_ARGS__; \
  80. static auto has_next() -> bool; \
  81. template<typename... Args> \
  82. static auto next(Args&&... args) -> decltype(auto); \
  83. }; \
  84. inline auto BOOST_OPENMETHOD_OVERRIDERS( \
  85. NAME)<__VA_ARGS__ ARGS>::has_next() -> bool { \
  86. return boost_openmethod_detail_locate_method_aux< \
  87. void ARGS>::type::has_next<fn>(); \
  88. } \
  89. template<typename... Args> \
  90. inline auto BOOST_OPENMETHOD_OVERRIDERS(NAME)<__VA_ARGS__ ARGS>::next( \
  91. Args&&... args) -> decltype(auto) { \
  92. return boost_openmethod_detail_locate_method_aux< \
  93. void ARGS>::type::next<fn>(std::forward<Args>(args)...); \
  94. }
  95. #define BOOST_OPENMETHOD_DETAIL_REGISTER_OVERRIDER(NAME, ARGS, ...) \
  96. BOOST_OPENMETHOD_REGISTER( \
  97. BOOST_OPENMETHOD_OVERRIDERS(NAME) < __VA_ARGS__ ARGS > \
  98. ::boost_openmethod_detail_locate_method_aux<void ARGS>::type:: \
  99. override< \
  100. BOOST_OPENMETHOD_OVERRIDERS(NAME) < __VA_ARGS__ ARGS>::fn >);
  101. #define BOOST_OPENMETHOD_DEFINE_OVERRIDER(NAME, ARGS, ...) \
  102. BOOST_OPENMETHOD_DETAIL_REGISTER_OVERRIDER(NAME, ARGS, __VA_ARGS__) \
  103. auto BOOST_OPENMETHOD_OVERRIDER(NAME, ARGS, __VA_ARGS__)::fn ARGS \
  104. -> boost::mp11::mp_back<boost::mp11::mp_list<__VA_ARGS__>>
  105. #define BOOST_OPENMETHOD_OVERRIDE(NAME, ARGS, ...) \
  106. BOOST_OPENMETHOD_DECLARE_OVERRIDER(NAME, ARGS, __VA_ARGS__) \
  107. BOOST_OPENMETHOD_DEFINE_OVERRIDER(NAME, ARGS, __VA_ARGS__)
  108. #define BOOST_OPENMETHOD_INLINE_OVERRIDE(NAME, ARGS, ...) \
  109. BOOST_OPENMETHOD_DECLARE_OVERRIDER(NAME, ARGS, __VA_ARGS__) \
  110. BOOST_OPENMETHOD_DETAIL_REGISTER_OVERRIDER(NAME, ARGS, __VA_ARGS__) \
  111. inline auto BOOST_OPENMETHOD_OVERRIDER(NAME, ARGS, __VA_ARGS__)::fn ARGS \
  112. -> boost::mp11::mp_back<boost::mp11::mp_list<__VA_ARGS__>>
  113. #define BOOST_OPENMETHOD_CLASSES(...) \
  114. BOOST_OPENMETHOD_REGISTER(::boost::openmethod::use_classes<__VA_ARGS__>);
  115. #endif