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