multivisitors_preprocessor_based.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Boost.Varaint
  2. // Contains multivisitors that are implemented via preprocessor magic
  3. //
  4. // See http://www.boost.org for most recent version, including documentation.
  5. //
  6. // Copyright Antony Polukhin, 2013-2014.
  7. //
  8. // Distributed under the Boost
  9. // Software License, Version 1.0. (See accompanying file
  10. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
  11. #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP
  12. #define BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP
  13. #if defined(_MSC_VER)
  14. # pragma once
  15. #endif
  16. #include <boost/variant.hpp>
  17. #include <boost/bind.hpp>
  18. #include <boost/preprocessor/repetition.hpp>
  19. #include <boost/preprocessor/punctuation/comma_if.hpp>
  20. #include <boost/preprocessor/arithmetic/add.hpp>
  21. #include <boost/preprocessor/arithmetic/sub.hpp>
  22. #ifndef BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS
  23. # define BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS 4
  24. #endif
  25. namespace boost {
  26. namespace detail { namespace variant {
  27. template <class VisitorT, class Visitable1T, class Visitable2T>
  28. struct two_variables_holder {
  29. private:
  30. VisitorT& visitor_;
  31. Visitable1T& visitable1_;
  32. Visitable2T& visitable2_;
  33. // required to suppress warnings and ensure that we do not copy
  34. // this visitor
  35. two_variables_holder& operator=(const two_variables_holder&);
  36. public:
  37. typedef BOOST_DEDUCED_TYPENAME VisitorT::result_type result_type;
  38. explicit two_variables_holder(VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2) BOOST_NOEXCEPT
  39. : visitor_(visitor)
  40. , visitable1_(visitable1)
  41. , visitable2_(visitable2)
  42. {}
  43. #define BOOST_VARIANT_OPERATOR_BEG() \
  44. return ::boost::apply_visitor( \
  45. ::boost::bind<result_type>(boost::ref(visitor_), _1, _2 \
  46. /**/
  47. #define BOOST_VARIANT_OPERATOR_END() \
  48. ), visitable1_, visitable2_); \
  49. /**/
  50. #define BOOST_VARANT_VISITORS_VARIABLES_PRINTER(z, n, data) \
  51. BOOST_PP_COMMA() boost::ref( BOOST_PP_CAT(vis, n) ) \
  52. /**/
  53. #define BOOST_VARIANT_VISIT(z, n, data) \
  54. template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ADD(n, 1), class VisitableUnwrapped)> \
  55. result_type operator()( \
  56. BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ADD(n, 1), VisitableUnwrapped, & vis) \
  57. ) const \
  58. { \
  59. BOOST_VARIANT_OPERATOR_BEG() \
  60. BOOST_PP_REPEAT(BOOST_PP_ADD(n, 1), BOOST_VARANT_VISITORS_VARIABLES_PRINTER, ~) \
  61. BOOST_VARIANT_OPERATOR_END() \
  62. } \
  63. /**/
  64. BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, ~)
  65. #undef BOOST_VARIANT_OPERATOR_BEG
  66. #undef BOOST_VARIANT_OPERATOR_END
  67. #undef BOOST_VARANT_VISITORS_VARIABLES_PRINTER
  68. #undef BOOST_VARIANT_VISIT
  69. };
  70. template <class VisitorT, class Visitable1T, class Visitable2T>
  71. inline two_variables_holder<VisitorT, Visitable1T, Visitable2T> make_two_variables_holder(
  72. VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2
  73. ) BOOST_NOEXCEPT
  74. {
  75. return two_variables_holder<VisitorT, Visitable1T, Visitable2T>(visitor, visitable1, visitable2);
  76. }
  77. template <class VisitorT, class Visitable1T, class Visitable2T>
  78. inline two_variables_holder<const VisitorT, Visitable1T, Visitable2T> make_two_variables_holder(
  79. const VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2
  80. ) BOOST_NOEXCEPT
  81. {
  82. return two_variables_holder<const VisitorT, Visitable1T, Visitable2T>(visitor, visitable1, visitable2);
  83. }
  84. }} // namespace detail::variant
  85. #define BOOST_VARIANT_APPLY_VISITOR_BEG() \
  86. return ::boost::apply_visitor( \
  87. boost::detail::variant::make_two_variables_holder(visitor, var0 , var1), \
  88. var2 \
  89. /**/
  90. #define BOOST_VARIANT_APPLY_VISITOR_END() \
  91. ); \
  92. /**/
  93. #define BOOST_VARANT_VISITORS_VARIABLES_PRINTER(z, n, data) \
  94. BOOST_PP_COMMA() BOOST_PP_CAT(var, BOOST_PP_ADD(n, 3)) \
  95. /**/
  96. #define BOOST_VARIANT_VISIT(z, n, data) \
  97. template <class Visitor BOOST_PP_COMMA() BOOST_PP_ENUM_PARAMS(BOOST_PP_ADD(n, 3), class T)> \
  98. inline BOOST_DEDUCED_TYPENAME Visitor::result_type apply_visitor( \
  99. data BOOST_PP_COMMA() BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ADD(n, 3), T, & var) \
  100. ) \
  101. { \
  102. BOOST_VARIANT_APPLY_VISITOR_BEG() \
  103. BOOST_PP_REPEAT(n, BOOST_VARANT_VISITORS_VARIABLES_PRINTER, ~) \
  104. BOOST_VARIANT_APPLY_VISITOR_END() \
  105. } \
  106. /**/
  107. BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, const Visitor& visitor)
  108. BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, Visitor& visitor)
  109. #undef BOOST_VARIANT_APPLY_VISITOR_BEG
  110. #undef BOOST_VARIANT_APPLY_VISITOR_END
  111. #undef BOOST_VARANT_VISITORS_VARIABLES_PRINTER
  112. #undef BOOST_VARIANT_VISIT
  113. } // namespace boost
  114. #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP