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