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
146
147
148
149
150
151
152
//  Boost.Varaint
//  Contains multivisitors that are implemented via variadic templates, std::tuple
//  and decltype(auto)
//
//  See http://www.boost.org for most recent version, including documentation.
//
//  Copyright Antony Polukhin, 2013-2014.
//
//  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_MULTIVISITORS_CPP14_BASED_HPP
#define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP
 
#if defined(_MSC_VER)
# pragma once
#endif
 
#include <boost/variant/detail/multivisitors_cpp14_based.hpp>
#include <tuple>
 
namespace boost {
 
namespace detail { namespace variant {
 
    // Forward declaration
    template <typename Visitor, typename Visitables, typename... Values>
    class one_by_one_visitor_and_value_referer_cpp14;
 
    template <typename Visitor, typename Visitables, typename... Values>
    inline one_by_one_visitor_and_value_referer_cpp14<Visitor, Visitables, Values... >
        make_one_by_one_visitor_and_value_referer_cpp14(
            Visitor& visitor, Visitables visitables, std::tuple<Values...> values
        )
    {
        return one_by_one_visitor_and_value_referer_cpp14<Visitor, Visitables, Values... > (
            visitor, visitables, values
        );
    }
 
    template <typename Visitor, typename Visitables, typename... Values>
    class one_by_one_visitor_and_value_referer_cpp14
    {
        Visitor&                        visitor_;
        std::tuple<Values...>           values_;
        Visitables                      visitables_;
 
    public: // structors
        one_by_one_visitor_and_value_referer_cpp14(
                    Visitor& visitor, Visitables visitables, std::tuple<Values...> values
                ) BOOST_NOEXCEPT
            : visitor_(visitor)
            , values_(values)
            , visitables_(visitables)
        {}
 
    public: // visitor interfaces
        template <typename Value>
        decltype(auto) operator()(Value&& value) const
        {
            return ::boost::apply_visitor(
                make_one_by_one_visitor_and_value_referer_cpp14(
                    visitor_,
                    tuple_tail(visitables_),
                    std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value)))
                )
                , unwrap(std::get<0>(visitables_)) // getting Head element
            );
        }
 
    private:
        one_by_one_visitor_and_value_referer_cpp14& operator=(const one_by_one_visitor_and_value_referer_cpp14&);
    };
 
    template <typename Visitor, typename... Values>
    class one_by_one_visitor_and_value_referer_cpp14<Visitor, std::tuple<>, Values...>
    {
        Visitor&                        visitor_;
        std::tuple<Values...>           values_;
 
    public:
        one_by_one_visitor_and_value_referer_cpp14(
                    Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values...> values
                ) BOOST_NOEXCEPT
            : visitor_(visitor)
            , values_(values)
        {}
 
        template <class Tuple, std::size_t... I>
        decltype(auto) do_call(Tuple t, index_sequence<I...>) const {
            return visitor_(unwrap(std::get<I>(t))...);
        }
 
        template <typename Value>
        decltype(auto) operator()(Value&& value) const
        {
            return do_call(
                std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))),
                make_index_sequence<sizeof...(Values) + 1>()
            );
        }
    };
 
}} // namespace detail::variant
 
    template <class Visitor, class T1, class T2, class T3, class... TN>
    inline decltype(auto) apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn,
        typename boost::disable_if<
            boost::detail::variant::has_result_type<Visitor>,
            bool
        >::type = true)
    {
        return boost::apply_visitor(
            ::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14(
                visitor,
                std::make_tuple(
                    ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
                    ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
                    ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
                    ),
                std::tuple<>()
            ),
            ::boost::forward<T1>(v1)
        );
    }
 
 
    template <class Visitor, class T1, class T2, class T3, class... TN>
    inline decltype(auto) apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn,
        typename boost::disable_if<
            boost::detail::variant::has_result_type<Visitor>,
            bool
        >::type = true)
    {
        return ::boost::apply_visitor(
            ::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14(
                visitor,
                std::make_tuple(
                    ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
                    ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
                    ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
                    ),
                std::tuple<>()
            ),
            ::boost::forward<T1>(v1)
        );
    }
 
} // namespace boost
 
#endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP