liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//-----------------------------------------------------------------------------
// boost variant/detail/apply_visitor_unary.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003 Eric Friedman
// Copyright (c) 2014-2020 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
 
#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
 
#include <boost/config.hpp>
#include <boost/move/utility.hpp>
 
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
#   include <boost/mpl/distance.hpp>
#   include <boost/mpl/advance.hpp>
#   include <boost/mpl/deref.hpp>
#   include <boost/mpl/size.hpp>
#   include <boost/utility/declval.hpp>
#   include <boost/core/enable_if.hpp>
#   include <boost/type_traits/copy_cv_ref.hpp>
#   include <boost/type_traits/remove_reference.hpp>
#   include <boost/variant/detail/has_result_type.hpp>
#endif
 
namespace boost {
 
//////////////////////////////////////////////////////////////////////////
// function template apply_visitor(visitor, visitable)
//
// Visits visitable with visitor.
//
 
//
// nonconst-visitor version:
//
 
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Visitor, typename Visitable>
inline typename Visitor::result_type
apply_visitor(Visitor& visitor, Visitable&& visitable)
{
    return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
}
#else
template <typename Visitor, typename Visitable>
inline typename Visitor::result_type
apply_visitor(Visitor& visitor, Visitable& visitable)
{
    return visitable.apply_visitor(visitor);
}
#endif
 
//
// const-visitor version:
//
 
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Visitor, typename Visitable>
inline typename Visitor::result_type
apply_visitor(const Visitor& visitor, Visitable&& visitable)
{
    return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
}
#else
template <typename Visitor, typename Visitable>
inline typename Visitor::result_type
apply_visitor(const Visitor& visitor, Visitable& visitable)
{
    return visitable.apply_visitor(visitor);
}
#endif
 
 
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
#define BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE
 
// C++14
namespace detail { namespace variant {
 
// This class serves only metaprogramming purposes. none of its methods must be called at runtime!
template <class Visitor, class Variant>
struct result_multideduce1 {
    typedef typename remove_reference<Variant>::type::types types;
    typedef typename boost::mpl::begin<types>::type begin_it;
    typedef typename boost::mpl::advance<
        begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
    >::type                                         last_it;
 
    template <class It, class Dummy = void> // avoid explicit specialization in class scope
    struct deduce_impl {
        typedef typename boost::mpl::next<It>::type next_t;
        typedef typename boost::mpl::deref<It>::type value_t;
        typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )
                              : boost::declval< typename deduce_impl<next_t>::type >()) type;
    };
 
    template <class Dummy>
    struct deduce_impl<last_it, Dummy> {
        typedef typename boost::mpl::deref<last_it>::type value_t;
        typedef decltype(boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )) type;
    };
 
    typedef typename deduce_impl<begin_it>::type type;
};
 
template <class Visitor, class Variant>
struct result_wrapper1
{
    typedef typename result_multideduce1<Visitor, Variant>::type result_type;
 
    Visitor&& visitor_;
    explicit result_wrapper1(Visitor&& visitor) BOOST_NOEXCEPT
        : visitor_(::boost::forward<Visitor>(visitor))
    {}
 
    template <class T>
    result_type operator()(T&& val) const {
        return visitor_(::boost::forward<T>(val));
    }
};
 
}} // namespace detail::variant
 
template <typename Visitor, typename Visitable>
inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable,
    typename boost::disable_if<
        boost::detail::variant::has_result_type<Visitor>,
        bool
    >::type = true)
{
    boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(::boost::forward<Visitor>(visitor));
    return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
}
 
#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
 
} // namespace boost
 
#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP