1 //  Boost.Varaint
2 //  Contains multivisitors that are implemented via variadic templates, std::tuple
3 //  and decltype(auto)
4 //
5 //  See http://www.boost.org for most recent version, including documentation.
6 //
7 //  Copyright Antony Polukhin, 2013-2014.
8 //
9 //  Distributed under the Boost
10 //  Software License, Version 1.0. (See accompanying file
11 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
12 
13 #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP
14 #define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP
15 
16 #if defined(_MSC_VER)
17 # pragma once
18 #endif
19 
20 #include <boost/variant/detail/multivisitors_cpp14_based.hpp>
21 #include <tuple>
22 
23 namespace boost {
24 
25 namespace detail { namespace variant {
26 
27     // Forward declaration
28     template <typename Visitor, typename Visitables, typename... Values>
29     class one_by_one_visitor_and_value_referer_cpp14;
30 
31     template <typename Visitor, typename Visitables, typename... Values>
32     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)33         make_one_by_one_visitor_and_value_referer_cpp14(
34             Visitor& visitor, Visitables visitables, std::tuple<Values...> values
35         )
36     {
37         return one_by_one_visitor_and_value_referer_cpp14<Visitor, Visitables, Values... > (
38             visitor, visitables, values
39         );
40     }
41 
42     template <typename Visitor, typename Visitables, typename... Values>
43     class one_by_one_visitor_and_value_referer_cpp14
44     {
45         Visitor&                        visitor_;
46         std::tuple<Values...>           values_;
47         Visitables                      visitables_;
48 
49     public: // structors
one_by_one_visitor_and_value_referer_cpp14(Visitor & visitor,Visitables visitables,std::tuple<Values...> values)50         one_by_one_visitor_and_value_referer_cpp14(
51                     Visitor& visitor, Visitables visitables, std::tuple<Values...> values
52                 ) BOOST_NOEXCEPT
53             : visitor_(visitor)
54             , values_(values)
55             , visitables_(visitables)
56         {}
57 
58     public: // visitor interfaces
59         template <typename Value>
operator ()(Value && value) const60         decltype(auto) operator()(Value&& value) const
61         {
62             return ::boost::apply_visitor(
63                 make_one_by_one_visitor_and_value_referer_cpp14(
64                     visitor_,
65                     tuple_tail(visitables_),
66                     std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value)))
67                 )
68                 , unwrap(std::get<0>(visitables_)) // getting Head element
69             );
70         }
71 
72     private:
73         one_by_one_visitor_and_value_referer_cpp14& operator=(const one_by_one_visitor_and_value_referer_cpp14&);
74     };
75 
76     template <typename Visitor, typename... Values>
77     class one_by_one_visitor_and_value_referer_cpp14<Visitor, std::tuple<>, Values...>
78     {
79         Visitor&                        visitor_;
80         std::tuple<Values...>           values_;
81 
82     public:
83         one_by_one_visitor_and_value_referer_cpp14(
84                     Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values...> values
85                 ) BOOST_NOEXCEPT
86             : visitor_(visitor)
87             , values_(values)
88         {}
89 
90         template <class Tuple, std::size_t... I>
91         decltype(auto) do_call(Tuple t, index_sequence<I...>) const {
92             return visitor_(unwrap(std::get<I>(t))...);
93         }
94 
95         template <typename Value>
96         decltype(auto) operator()(Value&& value) const
97         {
98             return do_call(
99                 std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))),
100                 make_index_sequence<sizeof...(Values) + 1>()
101             );
102         }
103     };
104 
105 }} // namespace detail::variant
106 
107     template <class Visitor, class T1, class T2, class T3, class... TN>
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)108     inline decltype(auto) apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn,
109         typename boost::disable_if<
110             boost::detail::variant::has_result_type<Visitor>,
111             bool
112         >::type = true)
113     {
114         return boost::apply_visitor(
115             ::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14(
116                 visitor,
117                 std::make_tuple(
118                     ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
119                     ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
120                     ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
121                     ),
122                 std::tuple<>()
123             ),
124             ::boost::forward<T1>(v1)
125         );
126     }
127 
128 
129     template <class Visitor, class T1, class T2, class T3, class... TN>
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)130     inline decltype(auto) apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn,
131         typename boost::disable_if<
132             boost::detail::variant::has_result_type<Visitor>,
133             bool
134         >::type = true)
135     {
136         return ::boost::apply_visitor(
137             ::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14(
138                 visitor,
139                 std::make_tuple(
140                     ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
141                     ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
142                     ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
143                     ),
144                 std::tuple<>()
145             ),
146             ::boost::forward<T1>(v1)
147         );
148     }
149 
150 } // namespace boost
151 
152 #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP
153 
154