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 12 #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP 13 #define BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP 14 15 #if defined(_MSC_VER) 16 # pragma once 17 #endif 18 19 #include <boost/variant.hpp> 20 #include <boost/bind.hpp> 21 22 #include <boost/preprocessor/repetition.hpp> 23 #include <boost/preprocessor/punctuation/comma_if.hpp> 24 #include <boost/preprocessor/arithmetic/add.hpp> 25 #include <boost/preprocessor/arithmetic/sub.hpp> 26 27 #ifndef BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS 28 # define BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS 4 29 #endif 30 31 namespace boost { 32 33 namespace detail { namespace variant { 34 35 template <class VisitorT, class Visitable1T, class Visitable2T> 36 struct two_variables_holder { 37 private: 38 VisitorT& visitor_; 39 Visitable1T& visitable1_; 40 Visitable2T& visitable2_; 41 42 // required to suppress warnings and ensure that we do not copy 43 // this visitor 44 two_variables_holder& operator=(const two_variables_holder&); 45 46 public: 47 typedef BOOST_DEDUCED_TYPENAME VisitorT::result_type result_type; 48 two_variables_holderboost::detail::variant::two_variables_holder49 explicit two_variables_holder(VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2) BOOST_NOEXCEPT 50 : visitor_(visitor) 51 , visitable1_(visitable1) 52 , visitable2_(visitable2) 53 {} 54 55 #define BOOST_VARIANT_OPERATOR_BEG() \ 56 return ::boost::apply_visitor( \ 57 ::boost::bind<result_type>(boost::ref(visitor_), _1, _2 \ 58 /**/ 59 60 #define BOOST_VARIANT_OPERATOR_END() \ 61 ), visitable1_, visitable2_); \ 62 /**/ 63 64 #define BOOST_VARANT_VISITORS_VARIABLES_PRINTER(z, n, data) \ 65 BOOST_PP_COMMA() boost::ref( BOOST_PP_CAT(vis, n) ) \ 66 /**/ 67 68 #define BOOST_VARIANT_VISIT(z, n, data) \ 69 template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ADD(n, 1), class VisitableUnwrapped)> \ 70 result_type operator()( \ 71 BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ADD(n, 1), VisitableUnwrapped, & vis) \ 72 ) const \ 73 { \ 74 BOOST_VARIANT_OPERATOR_BEG() \ 75 BOOST_PP_REPEAT(BOOST_PP_ADD(n, 1), BOOST_VARANT_VISITORS_VARIABLES_PRINTER, ~) \ 76 BOOST_VARIANT_OPERATOR_END() \ 77 } \ 78 /**/ 79 80 BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, ~) 81 #undef BOOST_VARIANT_OPERATOR_BEG 82 #undef BOOST_VARIANT_OPERATOR_END 83 #undef BOOST_VARANT_VISITORS_VARIABLES_PRINTER 84 #undef BOOST_VARIANT_VISIT 85 86 }; 87 88 template <class VisitorT, class Visitable1T, class Visitable2T> make_two_variables_holder(VisitorT & visitor,Visitable1T & visitable1,Visitable2T & visitable2)89 inline two_variables_holder<VisitorT, Visitable1T, Visitable2T> make_two_variables_holder( 90 VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2 91 ) BOOST_NOEXCEPT 92 { 93 return two_variables_holder<VisitorT, Visitable1T, Visitable2T>(visitor, visitable1, visitable2); 94 } 95 96 template <class VisitorT, class Visitable1T, class Visitable2T> make_two_variables_holder(const VisitorT & visitor,Visitable1T & visitable1,Visitable2T & visitable2)97 inline two_variables_holder<const VisitorT, Visitable1T, Visitable2T> make_two_variables_holder( 98 const VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2 99 ) BOOST_NOEXCEPT 100 { 101 return two_variables_holder<const VisitorT, Visitable1T, Visitable2T>(visitor, visitable1, visitable2); 102 } 103 104 }} // namespace detail::variant 105 106 #define BOOST_VARIANT_APPLY_VISITOR_BEG() \ 107 return ::boost::apply_visitor( \ 108 boost::detail::variant::make_two_variables_holder(visitor, var0 , var1), \ 109 var2 \ 110 /**/ 111 112 #define BOOST_VARIANT_APPLY_VISITOR_END() \ 113 ); \ 114 /**/ 115 116 #define BOOST_VARANT_VISITORS_VARIABLES_PRINTER(z, n, data) \ 117 BOOST_PP_COMMA() BOOST_PP_CAT(var, BOOST_PP_ADD(n, 3)) \ 118 /**/ 119 120 #define BOOST_VARIANT_VISIT(z, n, data) \ 121 template <class Visitor BOOST_PP_COMMA() BOOST_PP_ENUM_PARAMS(BOOST_PP_ADD(n, 3), class T)> \ 122 inline BOOST_DEDUCED_TYPENAME Visitor::result_type apply_visitor( \ 123 data BOOST_PP_COMMA() BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ADD(n, 3), T, & var) \ 124 ) \ 125 { \ 126 BOOST_VARIANT_APPLY_VISITOR_BEG() \ 127 BOOST_PP_REPEAT(n, BOOST_VARANT_VISITORS_VARIABLES_PRINTER, ~) \ 128 BOOST_VARIANT_APPLY_VISITOR_END() \ 129 } \ 130 /**/ 131 132 BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, const Visitor& visitor) 133 BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, Visitor& visitor) 134 135 #undef BOOST_VARIANT_APPLY_VISITOR_BEG 136 #undef BOOST_VARIANT_APPLY_VISITOR_END 137 #undef BOOST_VARANT_VISITORS_VARIABLES_PRINTER 138 #undef BOOST_VARIANT_VISIT 139 140 } // namespace boost 141 142 #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP 143 144