Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:32

0001 //  Boost.Varaint
0002 //  Contains multivisitors that are implemented via variadic templates and std::tuple
0003 //
0004 //  See http://www.boost.org for most recent version, including documentation.
0005 //
0006 //  Copyright Antony Polukhin, 2013-2023.
0007 //
0008 //  Distributed under the Boost
0009 //  Software License, Version 1.0. (See accompanying file
0010 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
0011 
0012 #ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
0013 #define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
0014 
0015 #if defined(_MSC_VER)
0016 # pragma once
0017 #endif
0018 
0019 #include <boost/variant/detail/apply_visitor_unary.hpp>
0020 #include <boost/variant/variant_fwd.hpp>
0021 #include <boost/type_traits/is_lvalue_reference.hpp>
0022 #include <boost/core/enable_if.hpp>
0023 
0024 #include <tuple>
0025 
0026 namespace boost { 
0027 
0028 namespace detail { namespace variant {
0029 
0030     // Implementing some of the C++14 features in C++11
0031     template <std::size_t... I> class index_sequence {};
0032 
0033     template <std::size_t N, std::size_t... I> 
0034     struct make_index_sequence 
0035         : make_index_sequence<N-1, N-1, I...> 
0036     {};
0037     template <std::size_t... I> 
0038     struct make_index_sequence<0, I...> 
0039         : index_sequence<I...> 
0040     {};
0041 
0042     template <typename T_, bool MoveSemantics_>
0043     struct MoveableWrapper //Just a reference with some metadata
0044     {
0045         typedef T_ T;
0046         static constexpr bool MoveSemantics = MoveSemantics_;
0047 
0048         T& v;
0049     };
0050 
0051     template <typename Tp, bool MoveSemantics>
0052     MoveableWrapper<Tp, MoveSemantics>
0053         wrap(Tp& t)
0054     {
0055         return MoveableWrapper<Tp, MoveSemantics>{t};
0056     }
0057 
0058     template <typename Wrapper>
0059     typename enable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type
0060         unwrap(Wrapper& w)
0061     {
0062         return std::move(w.v);
0063     }
0064 
0065     template <typename Wrapper>
0066     typename disable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type &
0067         unwrap(Wrapper& w)
0068     {
0069         return w.v;
0070     }
0071 
0072     // Implementing some of the helper tuple methods
0073     template <std::size_t... I, typename Tuple>
0074     std::tuple<typename std::tuple_element<I + 1, Tuple>::type...> 
0075         tuple_tail_impl(const Tuple& tpl, index_sequence<I...>)
0076     {
0077         return std::tuple<
0078             typename std::tuple_element<I + 1, Tuple>::type...
0079         > (std::get<I + 1>(tpl)...);
0080     }
0081 
0082     template <typename Head, typename... Tail>
0083     std::tuple<Tail...> tuple_tail(const std::tuple<Head, Tail...>& tpl)
0084     {
0085         return tuple_tail_impl(tpl, make_index_sequence<sizeof...(Tail)>());
0086     }
0087 
0088 
0089     // Forward declaration
0090     template <typename Visitor, typename Visitables, typename... Values>
0091     class one_by_one_visitor_and_value_referer;
0092 
0093     template <typename Visitor, typename Visitables, typename... Values>
0094     inline one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... >
0095         make_one_by_one_visitor_and_value_referer(
0096             Visitor& visitor, Visitables visitables, std::tuple<Values...> values
0097         )
0098     {
0099         return one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... > (
0100             visitor, visitables, values
0101         );
0102     }
0103 
0104     template <typename Visitor, typename Visitables, typename... Values>
0105     class one_by_one_visitor_and_value_referer
0106     {
0107         Visitor&                        visitor_;
0108         std::tuple<Values...>           values_;
0109         Visitables                      visitables_;
0110 
0111     public: // structors
0112         one_by_one_visitor_and_value_referer(
0113                     Visitor& visitor, Visitables visitables, std::tuple<Values...> values
0114                 ) BOOST_NOEXCEPT
0115             : visitor_(visitor)
0116             , values_(values)
0117             , visitables_(visitables)
0118         {}
0119 
0120     public: // visitor interfaces
0121         typedef typename Visitor::result_type result_type;
0122 
0123         template <typename Value>
0124         result_type operator()(Value&& value) const
0125         {
0126             return ::boost::apply_visitor(
0127                 make_one_by_one_visitor_and_value_referer(
0128                     visitor_,
0129                     tuple_tail(visitables_),
0130                     std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value)))
0131                 )
0132                 , unwrap(std::get<0>(visitables_)) // getting Head element
0133             );
0134         }
0135 
0136     private:
0137         one_by_one_visitor_and_value_referer& operator=(const one_by_one_visitor_and_value_referer&);
0138     };
0139 
0140     template <typename Visitor, typename... Values>
0141     class one_by_one_visitor_and_value_referer<Visitor, std::tuple<>, Values...>
0142     {
0143         Visitor&                        visitor_;
0144         std::tuple<Values...>           values_;
0145 
0146     public:
0147         one_by_one_visitor_and_value_referer(
0148                     Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values...> values
0149                 ) BOOST_NOEXCEPT
0150             : visitor_(visitor)
0151             , values_(values)
0152         {}
0153 
0154         typedef typename Visitor::result_type result_type;
0155 
0156         template <class Tuple, std::size_t... I>
0157         result_type do_call(Tuple t, index_sequence<I...>) const {
0158             return visitor_(unwrap(std::get<I>(t))...);
0159         }
0160 
0161         template <typename Value>
0162         result_type operator()(Value&& value) const
0163         {
0164             return do_call(
0165                 std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))),
0166                 make_index_sequence<sizeof...(Values) + 1>()
0167             );
0168         }
0169     };
0170 
0171 }} // namespace detail::variant
0172 
0173     template <class Visitor, class T1, class T2, class T3, class... TN>
0174     inline typename Visitor::result_type
0175         apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
0176     {
0177         return ::boost::apply_visitor(
0178             ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
0179                 visitor,
0180                 std::make_tuple(
0181                     ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
0182                     ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
0183                     ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
0184                     ),
0185                 std::tuple<>()
0186                 ),
0187                 std::forward<T1>(v1)
0188             );
0189     }
0190     
0191     template <class Visitor, class T1, class T2, class T3, class... TN>
0192     inline typename Visitor::result_type
0193         apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
0194     {
0195         return ::boost::apply_visitor(
0196             ::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
0197                 visitor,
0198                 std::make_tuple(
0199                     ::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
0200                     ::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
0201                     ::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
0202                     ),
0203                 std::tuple<>()
0204                 ),
0205                 std::forward<T1>(v1)
0206             );
0207     }
0208 
0209 } // namespace boost
0210 
0211 #endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
0212