Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / hana / ext / std / tuple.hpp
1 /*!
2 @file
3 Adapts `std::tuple` for use with Hana.
4
5 @copyright Louis Dionne 2013-2017
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8  */
9
10 #ifndef BOOST_HANA_EXT_STD_TUPLE_HPP
11 #define BOOST_HANA_EXT_STD_TUPLE_HPP
12
13 #include <boost/hana/bool.hpp>
14 #include <boost/hana/config.hpp>
15 #include <boost/hana/detail/decay.hpp>
16 #include <boost/hana/fwd/at.hpp>
17 #include <boost/hana/fwd/core/make.hpp>
18 #include <boost/hana/fwd/core/tag_of.hpp>
19 #include <boost/hana/fwd/drop_front.hpp>
20 #include <boost/hana/fwd/empty.hpp>
21 #include <boost/hana/fwd/flatten.hpp>
22 #include <boost/hana/fwd/front.hpp>
23 #include <boost/hana/fwd/is_empty.hpp>
24 #include <boost/hana/fwd/length.hpp>
25 #include <boost/hana/fwd/lift.hpp>
26 #include <boost/hana/integral_constant.hpp>
27
28 #include <cstddef>
29 #include <tuple>
30 #include <type_traits>
31 #include <utility>
32
33
34 #ifdef BOOST_HANA_DOXYGEN_INVOKED
35 namespace std {
36     //! @ingroup group-ext-std
37     //! Adapter for `std::tuple`s.
38     //!
39     //!
40     //! Modeled concepts
41     //! ----------------
42     //! A `std::tuple` is a model of the `Sequence` concept, and all the
43     //! concepts it refines. That makes it essentially the same as a Hana
44     //! tuple, although the complexity of some operations might differ from
45     //! that of Hana's tuple.
46     //!
47     //! @include example/ext/std/tuple.cpp
48     template <typename ...T>
49     struct tuple { };
50 }
51 #endif
52
53
54 BOOST_HANA_NAMESPACE_BEGIN
55     namespace ext { namespace std { struct tuple_tag; }}
56
57     template <typename ...Xs>
58     struct tag_of<std::tuple<Xs...>> {
59         using type = ext::std::tuple_tag;
60     };
61
62     //////////////////////////////////////////////////////////////////////////
63     // make
64     //////////////////////////////////////////////////////////////////////////
65     template <>
66     struct make_impl<ext::std::tuple_tag> {
67         template <typename ...Xs>
68         static constexpr decltype(auto) apply(Xs&& ...xs) {
69             return std::make_tuple(static_cast<Xs&&>(xs)...);
70         }
71     };
72
73     //////////////////////////////////////////////////////////////////////////
74     // Applicative
75     //////////////////////////////////////////////////////////////////////////
76     template <>
77     struct lift_impl<ext::std::tuple_tag> {
78         template <typename X>
79         static constexpr auto apply(X&& x) {
80             return std::tuple<typename detail::decay<X>::type>{
81                                                 static_cast<X&&>(x)};
82         }
83     };
84
85     //////////////////////////////////////////////////////////////////////////
86     // Monad
87     //////////////////////////////////////////////////////////////////////////
88     template <>
89     struct flatten_impl<ext::std::tuple_tag> {
90         template <typename Xs, std::size_t ...i>
91         static constexpr decltype(auto)
92         flatten_helper(Xs&& xs, std::index_sequence<i...>) {
93             return std::tuple_cat(std::get<i>(static_cast<Xs&&>(xs))...);
94         }
95
96         template <typename Xs>
97         static constexpr decltype(auto) apply(Xs&& xs) {
98             using Raw = typename std::remove_reference<Xs>::type;
99             constexpr std::size_t Length = std::tuple_size<Raw>::value;
100             return flatten_helper(static_cast<Xs&&>(xs),
101                                   std::make_index_sequence<Length>{});
102         }
103     };
104
105     //////////////////////////////////////////////////////////////////////////
106     // MonadPlus
107     //////////////////////////////////////////////////////////////////////////
108     template <>
109     struct empty_impl<ext::std::tuple_tag> {
110         static constexpr auto apply()
111         { return std::tuple<>{}; }
112     };
113
114     //////////////////////////////////////////////////////////////////////////
115     // Iterable
116     //////////////////////////////////////////////////////////////////////////
117     template <>
118     struct front_impl<ext::std::tuple_tag> {
119         template <typename Xs>
120         static constexpr decltype(auto) apply(Xs&& xs) {
121             return std::get<0>(static_cast<Xs&&>(xs));
122         }
123     };
124
125     template <>
126     struct drop_front_impl<ext::std::tuple_tag> {
127         template <std::size_t n, typename Xs, std::size_t ...i>
128         static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
129             return std::make_tuple(
130                 hana::at_c<n + i>(static_cast<Xs&&>(xs))...
131             );
132         }
133
134         template <typename Xs, typename N>
135         static constexpr auto apply(Xs&& xs, N const&) {
136             using Raw = typename std::remove_reference<Xs>::type;
137             constexpr std::size_t n = N::value;
138             constexpr auto len = std::tuple_size<Raw>::value;
139             return drop_front_helper<n>(static_cast<Xs&&>(xs),
140                     std::make_index_sequence<(n < len ? len - n : 0)>{});
141         }
142     };
143
144     template <>
145     struct is_empty_impl<ext::std::tuple_tag> {
146         template <typename ...Xs>
147         static constexpr auto apply(std::tuple<Xs...> const&)
148         { return hana::bool_c<sizeof...(Xs) == 0>; }
149     };
150
151     template <>
152     struct at_impl<ext::std::tuple_tag> {
153         template <typename Xs, typename N>
154         static constexpr decltype(auto) apply(Xs&& xs, N const&) {
155             constexpr std::size_t index = N::value;
156             return std::get<index>(static_cast<Xs&&>(xs));
157         }
158     };
159
160     //////////////////////////////////////////////////////////////////////////
161     // Foldable
162     //////////////////////////////////////////////////////////////////////////
163     template <>
164     struct length_impl<ext::std::tuple_tag> {
165         template <typename ...Xs>
166         static constexpr auto apply(std::tuple<Xs...> const&) {
167             return hana::size_c<sizeof...(Xs)>;
168         }
169     };
170
171     //////////////////////////////////////////////////////////////////////////
172     // Sequence
173     //////////////////////////////////////////////////////////////////////////
174     template <>
175     struct Sequence<ext::std::tuple_tag> {
176         static constexpr bool value = true;
177     };
178 BOOST_HANA_NAMESPACE_END
179
180 #endif // !BOOST_HANA_EXT_STD_TUPLE_HPP