]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
49 | 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)> \ | |
92f5a8d4 | 70 | result_type operator()( \ |
7c673cae FG |
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> | |
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> | |
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)> \ | |
92f5a8d4 | 122 | inline BOOST_DEDUCED_TYPENAME Visitor::result_type apply_visitor( \ |
7c673cae FG |
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 |