Ticket #8459: multivisitors.hpp

File multivisitors.hpp, 5.9 KB (added by Antony Polukhin, 10 years ago)

Multivisitors implementation

Line 
1// Boost.Varaint
2// Multivisitors defined here
3//
4// See http://www.boost.org for most recent version, including documentation.
5//
6// Copyright Antony Polukhin, 2013.
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_MULTIVISITORS_HPP
13#define BOOST_VARIANT_MULTIVISITORS_HPP
14
15#if defined(_MSC_VER) && (_MSC_VER >= 1020)
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
31namespace boost {
32
33namespace 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 supress warnings and enshure 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)> \
70 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(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
80BOOST_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
97}} // namespace detail::variant
98
99#define BOOST_VARIANT_APPLY_VISITOR_BEG() \
100 return ::boost::apply_visitor( \
101 boost::detail::variant::make_two_variables_holder(visitor, var0 , var1), \
102 var2 \
103 /**/
104
105#define BOOST_VARIANT_APPLY_VISITOR_END() \
106 ); \
107 /**/
108
109#define BOOST_VARANT_VISITORS_VARIABLES_PRINTER(z, n, data) \
110 BOOST_PP_COMMA() BOOST_PP_CAT(var, BOOST_PP_ADD(n, 3)) \
111 /**/
112
113#define BOOST_VARIANT_VISIT(z, n, data) \
114 template <class Visitor BOOST_PP_COMMA() BOOST_PP_ENUM_PARAMS(BOOST_PP_ADD(n, 3), class T)> \
115 inline BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(BOOST_DEDUCED_TYPENAME Visitor::result_type) apply_visitor( \
116 data BOOST_PP_COMMA() BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ADD(n, 3), T, & var) \
117 ) \
118 { \
119 BOOST_VARIANT_APPLY_VISITOR_BEG() \
120 BOOST_PP_REPEAT(n, BOOST_VARANT_VISITORS_VARIABLES_PRINTER, ~) \
121 BOOST_VARIANT_APPLY_VISITOR_END() \
122 } \
123 /**/
124
125BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, Visitor& visitor)
126BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, const Visitor& visitor)
127
128#undef BOOST_VARIANT_APPLY_VISITOR_BEG
129#undef BOOST_VARIANT_APPLY_VISITOR_END
130#undef BOOST_VARANT_VISITORS_VARIABLES_PRINTER
131#undef BOOST_VARIANT_VISIT
132
133} // namespace boost
134
135#endif // BOOST_VARIANT_MULTIVISITORS_HPP
136