]> git.lyx.org Git - features.git/blob - 3rdparty/boost/boost/variant/detail/apply_visitor_unary.hpp
Update to boost 1.68
[features.git] / 3rdparty / boost / boost / variant / detail / apply_visitor_unary.hpp
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>
19 #include <boost/move/utility.hpp>
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>
25 #include <boost/type_traits/remove_reference.hpp>
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
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
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 }
83 #endif
84
85 #undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE
86
87 //
88 // const-visitor version:
89 //
90
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
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 }
107 #endif
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
158     Visitor&& visitor_;
159     explicit result_wrapper1(Visitor&& visitor) BOOST_NOEXCEPT
160         : visitor_(::boost::forward<Visitor>(visitor))
161     {}
162
163     template <class T>
164     result_type operator()(T&& val) const {
165         return visitor_(::boost::forward<T>(val));
166     }
167 };
168
169 }} // namespace detail::variant
170
171 template <typename Visitor, typename Visitable>
172 inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable,
173     typename boost::disable_if<
174         boost::detail::variant::has_result_type<Visitor>
175     >::type* = 0)
176 {
177     boost::detail::variant::result_wrapper1<Visitor, typename remove_reference<Visitable>::type> cpp14_vis(::boost::forward<Visitor>(visitor));
178     return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
179 }
180
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