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
31namespace 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
43template <typename Visitor, typename Visitable>
44inline typename Visitor::result_type
45apply_visitor(Visitor& visitor, Visitable&& visitable)
46{
47 return std::forward<Visitable>(visitable).apply_visitor(visitor);
48}
49
50//
51// const-visitor version:
52//
53
54template <typename Visitor, typename Visitable>
55inline typename Visitor::result_type
56apply_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
66namespace detail { namespace variant {
67
68// This class serves only metaprogramming purposes. none of its methods must be called at runtime!
69template <class Visitor, class Variant>
70struct 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
94template <class Visitor, class Variant>
95struct 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
112template <typename Visitor, typename Visitable>
113inline 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

source code of boost/libs/variant/include/boost/variant/detail/apply_visitor_unary.hpp