3 Adapts `std::tuple` for use with Hana.
5 @copyright Louis Dionne 2013-2016
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_CONFIG_HAS_NO_STD_TUPLE_ADAPTER
35 # error The adapter for std::tuple is not supported with versions of \
36 libc++ prior to the one shipped with Clang 3.7 because of a bug \
37 in the tuple implementation.
41 #ifdef BOOST_HANA_DOXYGEN_INVOKED
43 //! @ingroup group-ext-std
44 //! Adapter for `std::tuple`s.
49 //! A `std::tuple` is a model of the `Sequence` concept, and all the
50 //! concepts it refines. That makes it essentially the same as a Hana
51 //! tuple, although the complexity of some operations might differ from
52 //! that of Hana's tuple.
54 //! @include example/ext/std/tuple.cpp
55 template <typename ...T>
61 BOOST_HANA_NAMESPACE_BEGIN
62 namespace ext { namespace std { struct tuple_tag; }}
64 template <typename ...Xs>
65 struct tag_of<std::tuple<Xs...>> {
66 using type = ext::std::tuple_tag;
69 //////////////////////////////////////////////////////////////////////////
71 //////////////////////////////////////////////////////////////////////////
73 struct make_impl<ext::std::tuple_tag> {
74 template <typename ...Xs>
75 static constexpr decltype(auto) apply(Xs&& ...xs) {
76 return std::make_tuple(static_cast<Xs&&>(xs)...);
80 //////////////////////////////////////////////////////////////////////////
82 //////////////////////////////////////////////////////////////////////////
84 struct lift_impl<ext::std::tuple_tag> {
86 static constexpr auto apply(X&& x) {
87 return std::tuple<typename detail::decay<X>::type>{
92 //////////////////////////////////////////////////////////////////////////
94 //////////////////////////////////////////////////////////////////////////
96 struct flatten_impl<ext::std::tuple_tag> {
97 template <typename Xs, std::size_t ...i>
98 static constexpr decltype(auto)
99 flatten_helper(Xs&& xs, std::index_sequence<i...>) {
100 #if defined(BOOST_HANA_CONFIG_LIBCPP_HAS_BUG_22806)
101 return std::tuple_cat(std::get<i>(xs)...);
103 return std::tuple_cat(std::get<i>(static_cast<Xs&&>(xs))...);
107 template <typename Xs>
108 static constexpr decltype(auto) apply(Xs&& xs) {
109 using Raw = typename std::remove_reference<Xs>::type;
110 constexpr std::size_t Length = std::tuple_size<Raw>::value;
111 return flatten_helper(static_cast<Xs&&>(xs),
112 std::make_index_sequence<Length>{});
116 //////////////////////////////////////////////////////////////////////////
118 //////////////////////////////////////////////////////////////////////////
120 struct empty_impl<ext::std::tuple_tag> {
121 static constexpr auto apply()
122 { return std::tuple<>{}; }
125 //////////////////////////////////////////////////////////////////////////
127 //////////////////////////////////////////////////////////////////////////
129 struct front_impl<ext::std::tuple_tag> {
130 template <typename Xs>
131 static constexpr decltype(auto) apply(Xs&& xs) {
132 return std::get<0>(static_cast<Xs&&>(xs));
137 struct drop_front_impl<ext::std::tuple_tag> {
138 template <std::size_t n, typename Xs, std::size_t ...i>
139 static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
140 return std::make_tuple(
141 hana::at_c<n + i>(static_cast<Xs&&>(xs))...
145 template <typename Xs, typename N>
146 static constexpr auto apply(Xs&& xs, N const&) {
147 using Raw = typename std::remove_reference<Xs>::type;
148 constexpr std::size_t n = N::value;
149 constexpr auto len = std::tuple_size<Raw>::value;
150 return drop_front_helper<n>(static_cast<Xs&&>(xs),
151 std::make_index_sequence<(n < len ? len - n : 0)>{});
156 struct is_empty_impl<ext::std::tuple_tag> {
157 template <typename ...Xs>
158 static constexpr auto apply(std::tuple<Xs...> const&)
159 { return hana::bool_c<sizeof...(Xs) == 0>; }
163 struct at_impl<ext::std::tuple_tag> {
164 template <typename Xs, typename N>
165 static constexpr decltype(auto) apply(Xs&& xs, N const&) {
166 constexpr std::size_t index = N::value;
167 return std::get<index>(static_cast<Xs&&>(xs));
171 //////////////////////////////////////////////////////////////////////////
173 //////////////////////////////////////////////////////////////////////////
175 struct length_impl<ext::std::tuple_tag> {
176 template <typename ...Xs>
177 static constexpr auto apply(std::tuple<Xs...> const&) {
178 return hana::size_c<sizeof...(Xs)>;
182 //////////////////////////////////////////////////////////////////////////
184 //////////////////////////////////////////////////////////////////////////
186 struct Sequence<ext::std::tuple_tag> {
187 static constexpr bool value = true;
189 BOOST_HANA_NAMESPACE_END
191 #endif // !BOOST_HANA_EXT_STD_TUPLE_HPP