3 Adapts `std::tuple` for use with Hana.
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)
10 #ifndef BOOST_HANA_EXT_STD_TUPLE_HPP
11 #define BOOST_HANA_EXT_STD_TUPLE_HPP
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>
30 #include <type_traits>
34 #ifdef BOOST_HANA_DOXYGEN_INVOKED
36 //! @ingroup group-ext-std
37 //! Adapter for `std::tuple`s.
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.
47 //! @include example/ext/std/tuple.cpp
48 template <typename ...T>
54 BOOST_HANA_NAMESPACE_BEGIN
55 namespace ext { namespace std { struct tuple_tag; }}
57 template <typename ...Xs>
58 struct tag_of<std::tuple<Xs...>> {
59 using type = ext::std::tuple_tag;
62 //////////////////////////////////////////////////////////////////////////
64 //////////////////////////////////////////////////////////////////////////
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)...);
73 //////////////////////////////////////////////////////////////////////////
75 //////////////////////////////////////////////////////////////////////////
77 struct lift_impl<ext::std::tuple_tag> {
79 static constexpr auto apply(X&& x) {
80 return std::tuple<typename detail::decay<X>::type>{
85 //////////////////////////////////////////////////////////////////////////
87 //////////////////////////////////////////////////////////////////////////
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))...);
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>{});
105 //////////////////////////////////////////////////////////////////////////
107 //////////////////////////////////////////////////////////////////////////
109 struct empty_impl<ext::std::tuple_tag> {
110 static constexpr auto apply()
111 { return std::tuple<>{}; }
114 //////////////////////////////////////////////////////////////////////////
116 //////////////////////////////////////////////////////////////////////////
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));
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))...
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)>{});
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>; }
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));
160 //////////////////////////////////////////////////////////////////////////
162 //////////////////////////////////////////////////////////////////////////
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)>;
171 //////////////////////////////////////////////////////////////////////////
173 //////////////////////////////////////////////////////////////////////////
175 struct Sequence<ext::std::tuple_tag> {
176 static constexpr bool value = true;
178 BOOST_HANA_NAMESPACE_END
180 #endif // !BOOST_HANA_EXT_STD_TUPLE_HPP