Chris@16
|
1 //-----------------------------------------------------------------------------
|
Chris@16
|
2 // boost variant/detail/apply_visitor_unary.hpp header file
|
Chris@16
|
3 // See http://www.boost.org for updates, documentation, and revision history.
|
Chris@16
|
4 //-----------------------------------------------------------------------------
|
Chris@16
|
5 //
|
Chris@101
|
6 // Copyright (c) 2002-2003 Eric Friedman
|
Chris@101
|
7 // Copyright (c) 2014 Antony Polukhin
|
Chris@16
|
8 //
|
Chris@16
|
9 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
10 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
11 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
|
Chris@16
|
14 #define BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
|
Chris@16
|
15
|
Chris@16
|
16 #include "boost/config.hpp"
|
Chris@16
|
17 #include "boost/detail/workaround.hpp"
|
Chris@16
|
18 #include "boost/variant/detail/generic_result_type.hpp"
|
Chris@16
|
19
|
Chris@16
|
20 #if BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
|
Chris@101
|
21 #include "boost/core/enable_if.hpp"
|
Chris@16
|
22 #include "boost/mpl/not.hpp"
|
Chris@16
|
23 #include "boost/type_traits/is_const.hpp"
|
Chris@16
|
24 #endif
|
Chris@16
|
25
|
Chris@101
|
26 #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
|
Chris@101
|
27 # include <boost/mpl/distance.hpp>
|
Chris@101
|
28 # include <boost/mpl/advance.hpp>
|
Chris@101
|
29 # include <boost/mpl/deref.hpp>
|
Chris@101
|
30 # include <boost/mpl/size.hpp>
|
Chris@101
|
31 # include <boost/utility/declval.hpp>
|
Chris@101
|
32 # include <boost/core/enable_if.hpp>
|
Chris@101
|
33 # include "boost/variant/detail/has_result_type.hpp"
|
Chris@101
|
34 #endif
|
Chris@101
|
35
|
Chris@16
|
36 namespace boost {
|
Chris@16
|
37
|
Chris@16
|
38 //////////////////////////////////////////////////////////////////////////
|
Chris@16
|
39 // function template apply_visitor(visitor, visitable)
|
Chris@16
|
40 //
|
Chris@16
|
41 // Visits visitable with visitor.
|
Chris@16
|
42 //
|
Chris@16
|
43
|
Chris@16
|
44 //
|
Chris@16
|
45 // nonconst-visitor version:
|
Chris@16
|
46 //
|
Chris@16
|
47
|
Chris@16
|
48 #if !BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
|
Chris@16
|
49
|
Chris@16
|
50 # define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
|
Chris@16
|
51 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
|
Chris@16
|
52 /**/
|
Chris@16
|
53
|
Chris@16
|
54 #else // EDG-based compilers
|
Chris@16
|
55
|
Chris@16
|
56 # define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
|
Chris@16
|
57 typename enable_if< \
|
Chris@16
|
58 mpl::not_< is_const< V > > \
|
Chris@16
|
59 , BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
|
Chris@16
|
60 >::type \
|
Chris@16
|
61 /**/
|
Chris@16
|
62
|
Chris@16
|
63 #endif // EDG-based compilers workaround
|
Chris@16
|
64
|
Chris@16
|
65 template <typename Visitor, typename Visitable>
|
Chris@16
|
66 inline
|
Chris@16
|
67 BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
|
Chris@16
|
68 apply_visitor(Visitor& visitor, Visitable& visitable)
|
Chris@16
|
69 {
|
Chris@16
|
70 return visitable.apply_visitor(visitor);
|
Chris@16
|
71 }
|
Chris@16
|
72
|
Chris@16
|
73 #undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE
|
Chris@16
|
74
|
Chris@16
|
75 //
|
Chris@16
|
76 // const-visitor version:
|
Chris@16
|
77 //
|
Chris@16
|
78
|
Chris@16
|
79 template <typename Visitor, typename Visitable>
|
Chris@16
|
80 inline
|
Chris@16
|
81 BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
|
Chris@16
|
82 apply_visitor(const Visitor& visitor, Visitable& visitable)
|
Chris@16
|
83 {
|
Chris@16
|
84 return visitable.apply_visitor(visitor);
|
Chris@16
|
85 }
|
Chris@16
|
86
|
Chris@101
|
87
|
Chris@101
|
88 #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
|
Chris@101
|
89
|
Chris@101
|
90 // C++14
|
Chris@101
|
91 namespace detail { namespace variant {
|
Chris@101
|
92
|
Chris@101
|
93 // This class serves only metaprogramming purposes. none of its methods must be called at runtime!
|
Chris@101
|
94 template <class Visitor, class Variant>
|
Chris@101
|
95 struct result_multideduce1 {
|
Chris@101
|
96 typedef typename Variant::types types;
|
Chris@101
|
97 typedef typename boost::mpl::begin<types>::type begin_it;
|
Chris@101
|
98 typedef typename boost::mpl::advance<
|
Chris@101
|
99 begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
|
Chris@101
|
100 >::type last_it;
|
Chris@101
|
101
|
Chris@101
|
102 // For metaprogramming purposes ONLY! Do not use this method (and class) at runtime!
|
Chris@101
|
103 static Visitor& vis() BOOST_NOEXCEPT {
|
Chris@101
|
104 // Functions that work with lambdas must be defined in same translation unit.
|
Chris@101
|
105 // Because of that, we can not use `boost::decval<Visitor&>()` here.
|
Chris@101
|
106 Visitor&(*f)() = 0; // pointer to function
|
Chris@101
|
107 return f();
|
Chris@101
|
108 }
|
Chris@101
|
109
|
Chris@101
|
110 static decltype(auto) deduce_impl(last_it, unsigned /*helper*/) {
|
Chris@101
|
111 typedef typename boost::mpl::deref<last_it>::type value_t;
|
Chris@101
|
112 return vis()( boost::declval< value_t& >() );
|
Chris@101
|
113 }
|
Chris@101
|
114
|
Chris@101
|
115 template <class It>
|
Chris@101
|
116 static decltype(auto) deduce_impl(It, unsigned helper) {
|
Chris@101
|
117 typedef typename boost::mpl::next<It>::type next_t;
|
Chris@101
|
118 typedef typename boost::mpl::deref<It>::type value_t;
|
Chris@101
|
119 if (helper == boost::mpl::distance<begin_it, It>::type::value) {
|
Chris@101
|
120 return deduce_impl(next_t(), ++helper);
|
Chris@101
|
121 }
|
Chris@101
|
122
|
Chris@101
|
123 return vis()( boost::declval< value_t& >() );
|
Chris@101
|
124 }
|
Chris@101
|
125
|
Chris@101
|
126 static decltype(auto) deduce() {
|
Chris@101
|
127 return deduce_impl(begin_it(), 0);
|
Chris@101
|
128 }
|
Chris@101
|
129 };
|
Chris@101
|
130
|
Chris@101
|
131 template <class Visitor, class Variant>
|
Chris@101
|
132 struct result_wrapper1
|
Chris@101
|
133 {
|
Chris@101
|
134 typedef decltype(result_multideduce1<Visitor, Variant>::deduce()) result_type;
|
Chris@101
|
135
|
Chris@101
|
136 Visitor& visitor_;
|
Chris@101
|
137 explicit result_wrapper1(Visitor& visitor) BOOST_NOEXCEPT
|
Chris@101
|
138 : visitor_(visitor)
|
Chris@101
|
139 {}
|
Chris@101
|
140
|
Chris@101
|
141 template <class T>
|
Chris@101
|
142 result_type operator()(T& val) const {
|
Chris@101
|
143 return visitor_(val);
|
Chris@101
|
144 }
|
Chris@101
|
145 };
|
Chris@101
|
146
|
Chris@101
|
147 }} // namespace detail::variant
|
Chris@101
|
148
|
Chris@101
|
149 template <typename Visitor, typename Visitable>
|
Chris@101
|
150 inline decltype(auto) apply_visitor(Visitor& visitor, Visitable& visitable,
|
Chris@101
|
151 typename boost::disable_if<
|
Chris@101
|
152 boost::detail::variant::has_result_type<Visitor>
|
Chris@101
|
153 >::type* = 0)
|
Chris@101
|
154 {
|
Chris@101
|
155 boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(visitor);
|
Chris@101
|
156 return visitable.apply_visitor(cpp14_vis);
|
Chris@101
|
157 }
|
Chris@101
|
158
|
Chris@101
|
159 template <typename Visitor, typename Visitable>
|
Chris@101
|
160 inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable& visitable,
|
Chris@101
|
161 typename boost::disable_if<
|
Chris@101
|
162 boost::detail::variant::has_result_type<Visitor>
|
Chris@101
|
163 >::type* = 0)
|
Chris@101
|
164 {
|
Chris@101
|
165 boost::detail::variant::result_wrapper1<const Visitor, Visitable> cpp14_vis(visitor);
|
Chris@101
|
166 return visitable.apply_visitor(cpp14_vis);
|
Chris@101
|
167 }
|
Chris@101
|
168
|
Chris@101
|
169 #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
|
Chris@16
|
170
|
Chris@16
|
171 } // namespace boost
|
Chris@16
|
172
|
Chris@16
|
173 #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
|