• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
applymake_impl68         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>
applylift_impl79         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)
flatten_helperflatten_impl92         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>
applyflatten_impl97         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> {
applyempty_impl110         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>
applyfront_impl120         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>
drop_front_helperdrop_front_impl128         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>
applydrop_front_impl135         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>
applyis_empty_impl147         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>
applyat_impl154         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>
applylength_impl166         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
181