Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:13:51

0001 /*!
0002 @file
0003 Defines `boost::hana::tuple`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Copyright Jason Rice 2017
0007 Distributed under the Boost Software License, Version 1.0.
0008 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0009  */
0010 
0011 #ifndef BOOST_HANA_TUPLE_HPP
0012 #define BOOST_HANA_TUPLE_HPP
0013 
0014 #include <boost/hana/fwd/tuple.hpp>
0015 
0016 #include <boost/hana/basic_tuple.hpp>
0017 #include <boost/hana/bool.hpp>
0018 #include <boost/hana/config.hpp>
0019 #include <boost/hana/detail/decay.hpp>
0020 #include <boost/hana/detail/fast_and.hpp>
0021 #include <boost/hana/detail/index_if.hpp>
0022 #include <boost/hana/detail/intrinsics.hpp>
0023 #include <boost/hana/detail/operators/adl.hpp>
0024 #include <boost/hana/detail/operators/comparable.hpp>
0025 #include <boost/hana/detail/operators/iterable.hpp>
0026 #include <boost/hana/detail/operators/monad.hpp>
0027 #include <boost/hana/detail/operators/orderable.hpp>
0028 #include <boost/hana/fwd/at.hpp>
0029 #include <boost/hana/fwd/core/make.hpp>
0030 #include <boost/hana/fwd/drop_front.hpp>
0031 #include <boost/hana/fwd/index_if.hpp>
0032 #include <boost/hana/fwd/is_empty.hpp>
0033 #include <boost/hana/fwd/length.hpp>
0034 #include <boost/hana/fwd/optional.hpp>
0035 #include <boost/hana/fwd/unpack.hpp>
0036 #include <boost/hana/type.hpp> // required by fwd decl of tuple_t
0037 
0038 #include <cstddef>
0039 #include <type_traits>
0040 #include <utility>
0041 
0042 
0043 namespace boost { namespace hana {
0044     namespace detail {
0045         template <typename Xs, typename Ys, std::size_t ...n>
0046         constexpr void assign(Xs& xs, Ys&& ys, std::index_sequence<n...>) {
0047             int sequence[] = {int{}, ((void)(
0048                 hana::at_c<n>(xs) = hana::at_c<n>(static_cast<Ys&&>(ys))
0049             ), int{})...};
0050             (void)sequence;
0051         }
0052 
0053         struct from_index_sequence_t { };
0054 
0055         template <typename Tuple, typename ...Yn>
0056         struct is_same_tuple : std::false_type { };
0057 
0058         template <typename Tuple>
0059         struct is_same_tuple<typename detail::decay<Tuple>::type, Tuple>
0060             : std::true_type
0061         { };
0062 
0063         template <bool SameTuple, bool SameNumberOfElements, typename Tuple, typename ...Yn>
0064         struct enable_tuple_variadic_ctor;
0065 
0066         template <typename ...Xn, typename ...Yn>
0067         struct enable_tuple_variadic_ctor<false, true, hana::tuple<Xn...>, Yn...>
0068             : std::enable_if<
0069                 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
0070             >
0071         { };
0072     }
0073 
0074     //////////////////////////////////////////////////////////////////////////
0075     // tuple
0076     //////////////////////////////////////////////////////////////////////////
0077     template <>
0078 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
0079     struct __declspec(empty_bases) tuple<> final
0080 #else
0081     struct tuple<> final
0082 #endif
0083         : detail::operators::adl<tuple<>>
0084         , detail::iterable_operators<tuple<>>
0085     {
0086         constexpr tuple() { }
0087         using hana_tag = tuple_tag;
0088     };
0089 
0090     template <typename ...Xn>
0091 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
0092     struct __declspec(empty_bases) tuple final
0093 #else
0094     struct tuple final
0095 #endif
0096         : detail::operators::adl<tuple<Xn...>>
0097         , detail::iterable_operators<tuple<Xn...>>
0098     {
0099         basic_tuple<Xn...> storage_;
0100         using hana_tag = tuple_tag;
0101 
0102     private:
0103         template <typename Other, std::size_t ...n>
0104         explicit constexpr tuple(detail::from_index_sequence_t, std::index_sequence<n...>, Other&& other)
0105             : storage_(hana::at_c<n>(static_cast<Other&&>(other))...)
0106         { }
0107 
0108     public:
0109         template <typename ...dummy, typename = typename std::enable_if<
0110             detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, dummy...)...>::value
0111         >::type>
0112         constexpr tuple()
0113             : storage_()
0114         { }
0115 
0116         template <typename ...dummy, typename = typename std::enable_if<
0117             detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
0118         >::type>
0119         constexpr tuple(Xn const& ...xn)
0120             : storage_(xn...)
0121         { }
0122 
0123         template <typename ...Yn, typename = typename detail::enable_tuple_variadic_ctor<
0124             detail::is_same_tuple<tuple, Yn...>::value,
0125             sizeof...(Xn) == sizeof...(Yn), tuple, Yn...
0126         >::type>
0127         constexpr tuple(Yn&& ...yn)
0128             : storage_(static_cast<Yn&&>(yn)...)
0129         { }
0130 
0131         template <typename ...Yn, typename = typename std::enable_if<
0132             detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn const&)...>::value
0133         >::type>
0134         constexpr tuple(tuple<Yn...> const& other)
0135             : tuple(detail::from_index_sequence_t{},
0136                     std::make_index_sequence<sizeof...(Xn)>{},
0137                     other.storage_)
0138         { }
0139 
0140         template <typename ...Yn, typename = typename std::enable_if<
0141             detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
0142         >::type>
0143         constexpr tuple(tuple<Yn...>&& other)
0144             : tuple(detail::from_index_sequence_t{},
0145                     std::make_index_sequence<sizeof...(Xn)>{},
0146                     static_cast<tuple<Yn...>&&>(other).storage_)
0147         { }
0148 
0149         // The three following constructors are required to make sure that
0150         // the tuple(Yn&&...) constructor is _not_ preferred over the copy
0151         // constructor for unary tuples containing a type that is constructible
0152         // from tuple<...>. See test/tuple/cnstr.trap.cpp
0153         template <typename ...dummy, typename = typename std::enable_if<
0154             detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
0155         >::type>
0156         constexpr tuple(tuple const& other)
0157             : tuple(detail::from_index_sequence_t{},
0158                     std::make_index_sequence<sizeof...(Xn)>{},
0159                     other.storage_)
0160         { }
0161 
0162         template <typename ...dummy, typename = typename std::enable_if<
0163             detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
0164         >::type>
0165         constexpr tuple(tuple& other)
0166             : tuple(const_cast<tuple const&>(other))
0167         { }
0168 
0169         template <typename ...dummy, typename = typename std::enable_if<
0170             detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn&&, dummy...)...>::value
0171         >::type>
0172         constexpr tuple(tuple&& other)
0173             : tuple(detail::from_index_sequence_t{},
0174                     std::make_index_sequence<sizeof...(Xn)>{},
0175                     static_cast<tuple&&>(other).storage_)
0176         { }
0177 
0178 
0179         template <typename ...Yn, typename = typename std::enable_if<
0180             detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn const&)...>::value
0181         >::type>
0182         constexpr tuple& operator=(tuple<Yn...> const& other) {
0183             detail::assign(this->storage_, other.storage_,
0184                            std::make_index_sequence<sizeof...(Xn)>{});
0185             return *this;
0186         }
0187 
0188         template <typename ...Yn, typename = typename std::enable_if<
0189             detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn&&)...>::value
0190         >::type>
0191         constexpr tuple& operator=(tuple<Yn...>&& other) {
0192             detail::assign(this->storage_, static_cast<tuple<Yn...>&&>(other).storage_,
0193                            std::make_index_sequence<sizeof...(Xn)>{});
0194             return *this;
0195         }
0196     };
0197 
0198     //////////////////////////////////////////////////////////////////////////
0199     // Operators
0200     //////////////////////////////////////////////////////////////////////////
0201     namespace detail {
0202         template <>
0203         struct comparable_operators<tuple_tag> {
0204             static constexpr bool value = true;
0205         };
0206         template <>
0207         struct orderable_operators<tuple_tag> {
0208             static constexpr bool value = true;
0209         };
0210         template <>
0211         struct monad_operators<tuple_tag> {
0212             static constexpr bool value = true;
0213         };
0214     }
0215 
0216     //////////////////////////////////////////////////////////////////////////
0217     // Foldable
0218     //////////////////////////////////////////////////////////////////////////
0219     template <>
0220     struct unpack_impl<tuple_tag> {
0221         template <typename F>
0222         static constexpr decltype(auto) apply(tuple<>&&, F&& f)
0223         { return static_cast<F&&>(f)(); }
0224         template <typename F>
0225         static constexpr decltype(auto) apply(tuple<>&, F&& f)
0226         { return static_cast<F&&>(f)(); }
0227         template <typename F>
0228         static constexpr decltype(auto) apply(tuple<> const&, F&& f)
0229         { return static_cast<F&&>(f)(); }
0230 
0231         template <typename Xs, typename F>
0232         static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
0233             return hana::unpack(static_cast<Xs&&>(xs).storage_, static_cast<F&&>(f));
0234         }
0235     };
0236 
0237     template <>
0238     struct length_impl<tuple_tag> {
0239         template <typename ...Xs>
0240         static constexpr auto apply(tuple<Xs...> const&)
0241         { return hana::size_c<sizeof...(Xs)>; }
0242     };
0243 
0244     //////////////////////////////////////////////////////////////////////////
0245     // Iterable
0246     //////////////////////////////////////////////////////////////////////////
0247     template <>
0248     struct at_impl<tuple_tag> {
0249         template <typename Xs, typename N>
0250         static constexpr decltype(auto) apply(Xs&& xs, N const&) {
0251             constexpr std::size_t index = N::value;
0252             return hana::at_c<index>(static_cast<Xs&&>(xs).storage_);
0253         }
0254     };
0255 
0256     template <>
0257     struct drop_front_impl<tuple_tag> {
0258         template <std::size_t N, typename Xs, std::size_t ...i>
0259         static constexpr auto helper(Xs&& xs, std::index_sequence<i...>) {
0260             return hana::make<tuple_tag>(hana::at_c<i+N>(static_cast<Xs&&>(xs))...);
0261         }
0262 
0263         template <typename Xs, typename N>
0264         static constexpr auto apply(Xs&& xs, N const&) {
0265             constexpr std::size_t len = decltype(hana::length(xs))::value;
0266             return helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence<
0267                 (N::value < len) ? len - N::value : 0
0268             >{});
0269         }
0270     };
0271 
0272     template <>
0273     struct is_empty_impl<tuple_tag> {
0274         template <typename ...Xs>
0275         static constexpr auto apply(tuple<Xs...> const&)
0276         { return hana::bool_c<sizeof...(Xs) == 0>; }
0277     };
0278 
0279     // compile-time optimizations (to reduce the # of function instantiations)
0280     template <std::size_t n, typename ...Xs>
0281     constexpr decltype(auto) at_c(tuple<Xs...> const& xs) {
0282         return hana::at_c<n>(xs.storage_);
0283     }
0284 
0285     template <std::size_t n, typename ...Xs>
0286     constexpr decltype(auto) at_c(tuple<Xs...>& xs) {
0287         return hana::at_c<n>(xs.storage_);
0288     }
0289 
0290     template <std::size_t n, typename ...Xs>
0291     constexpr decltype(auto) at_c(tuple<Xs...>&& xs) {
0292         return hana::at_c<n>(static_cast<tuple<Xs...>&&>(xs).storage_);
0293     }
0294 
0295     template <>
0296     struct index_if_impl<tuple_tag> {
0297         template <typename ...Xs, typename Pred>
0298         static constexpr auto apply(tuple<Xs...> const&, Pred const&)
0299             -> typename detail::index_if<Pred, Xs...>::type
0300         { return {}; }
0301     };
0302 
0303     //////////////////////////////////////////////////////////////////////////
0304     // Sequence
0305     //////////////////////////////////////////////////////////////////////////
0306     template <>
0307     struct Sequence<tuple_tag> {
0308         static constexpr bool value = true;
0309     };
0310 
0311     template <>
0312     struct make_impl<tuple_tag> {
0313         template <typename ...Xs>
0314         static constexpr
0315         tuple<typename detail::decay<Xs>::type...> apply(Xs&& ...xs)
0316         { return {static_cast<Xs&&>(xs)...}; }
0317     };
0318 }} // end namespace boost::hana
0319 
0320 #endif // !BOOST_HANA_TUPLE_HPP