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-2024 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 <utility> |
18 | |
19 | #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) |
20 | # include <boost/mpl/distance.hpp> |
21 | # include <boost/mpl/advance.hpp> |
22 | # include <boost/mpl/deref.hpp> |
23 | # include <boost/mpl/size.hpp> |
24 | # include <boost/utility/declval.hpp> |
25 | # include <boost/core/enable_if.hpp> |
26 | # include <boost/type_traits/copy_cv_ref.hpp> |
27 | # include <boost/type_traits/remove_reference.hpp> |
28 | # include <boost/variant/detail/has_result_type.hpp> |
29 | #endif |
30 | |
31 | namespace boost { |
32 | |
33 | ////////////////////////////////////////////////////////////////////////// |
34 | // function template apply_visitor(visitor, visitable) |
35 | // |
36 | // Visits visitable with visitor. |
37 | // |
38 | |
39 | // |
40 | // nonconst-visitor version: |
41 | // |
42 | |
43 | template <typename Visitor, typename Visitable> |
44 | inline typename Visitor::result_type |
45 | apply_visitor(Visitor& visitor, Visitable&& visitable) |
46 | { |
47 | return std::forward<Visitable>(visitable).apply_visitor(visitor); |
48 | } |
49 | |
50 | // |
51 | // const-visitor version: |
52 | // |
53 | |
54 | template <typename Visitor, typename Visitable> |
55 | inline typename Visitor::result_type |
56 | apply_visitor(const Visitor& visitor, Visitable&& visitable) |
57 | { |
58 | return std::forward<Visitable>(visitable).apply_visitor(visitor); |
59 | } |
60 | |
61 | |
62 | #if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) |
63 | #define BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE |
64 | |
65 | // C++14 |
66 | namespace detail { namespace variant { |
67 | |
68 | // This class serves only metaprogramming purposes. none of its methods must be called at runtime! |
69 | template <class Visitor, class Variant> |
70 | struct result_multideduce1 { |
71 | typedef typename remove_reference<Variant>::type::types types; |
72 | typedef typename boost::mpl::begin<types>::type begin_it; |
73 | typedef typename boost::mpl::advance< |
74 | begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1> |
75 | >::type last_it; |
76 | |
77 | template <class It, class Dummy = void> // avoid explicit specialization in class scope |
78 | struct deduce_impl { |
79 | typedef typename boost::mpl::next<It>::type next_t; |
80 | typedef typename boost::mpl::deref<It>::type value_t; |
81 | typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() ) |
82 | : boost::declval< typename deduce_impl<next_t>::type >()) type; |
83 | }; |
84 | |
85 | template <class Dummy> |
86 | struct deduce_impl<last_it, Dummy> { |
87 | typedef typename boost::mpl::deref<last_it>::type value_t; |
88 | typedef decltype(boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )) type; |
89 | }; |
90 | |
91 | typedef typename deduce_impl<begin_it>::type type; |
92 | }; |
93 | |
94 | template <class Visitor, class Variant> |
95 | struct result_wrapper1 |
96 | { |
97 | typedef typename result_multideduce1<Visitor, Variant>::type result_type; |
98 | |
99 | Visitor&& visitor_; |
100 | explicit result_wrapper1(Visitor&& visitor) BOOST_NOEXCEPT |
101 | : visitor_(std::forward<Visitor>(visitor)) |
102 | {} |
103 | |
104 | template <class T> |
105 | result_type operator()(T&& val) const { |
106 | return visitor_(std::forward<T>(val)); |
107 | } |
108 | }; |
109 | |
110 | }} // namespace detail::variant |
111 | |
112 | template <typename Visitor, typename Visitable> |
113 | inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable, |
114 | typename boost::disable_if< |
115 | boost::detail::variant::has_result_type<Visitor>, |
116 | bool |
117 | >::type = true) |
118 | { |
119 | boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(std::forward<Visitor>(visitor)); |
120 | return std::forward<Visitable>(visitable).apply_visitor(cpp14_vis); |
121 | } |
122 | |
123 | #endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) |
124 | |
125 | } // namespace boost |
126 | |
127 | #endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP |
128 | |