1 /*! 2 @file 3 Defines `boost::hana::basic_tuple`. 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_BASIC_TUPLE_HPP 11 #define BOOST_HANA_BASIC_TUPLE_HPP 12 13 #include <boost/hana/fwd/basic_tuple.hpp> 14 15 #include <boost/hana/config.hpp> 16 #include <boost/hana/detail/decay.hpp> 17 #include <boost/hana/detail/ebo.hpp> 18 #include <boost/hana/fwd/at.hpp> 19 #include <boost/hana/fwd/bool.hpp> 20 #include <boost/hana/fwd/concept/sequence.hpp> 21 #include <boost/hana/fwd/core/make.hpp> 22 #include <boost/hana/fwd/core/tag_of.hpp> 23 #include <boost/hana/fwd/drop_front.hpp> 24 #include <boost/hana/fwd/integral_constant.hpp> 25 #include <boost/hana/fwd/is_empty.hpp> 26 #include <boost/hana/fwd/length.hpp> 27 #include <boost/hana/fwd/transform.hpp> 28 #include <boost/hana/fwd/unpack.hpp> 29 30 #include <cstddef> 31 #include <type_traits> 32 #include <utility> 33 34 35 BOOST_HANA_NAMESPACE_BEGIN 36 namespace detail { 37 ////////////////////////////////////////////////////////////////////// 38 // basic_tuple_impl<n, Xn> 39 ////////////////////////////////////////////////////////////////////// 40 template <std::size_t> struct bti; // basic_tuple_index 41 42 struct from_other { }; 43 44 template <typename Indices, typename ...Xn> 45 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE 46 struct __declspec(empty_bases) basic_tuple_impl; 47 #else 48 struct basic_tuple_impl; 49 #endif 50 51 template <std::size_t ...n, typename ...Xn> 52 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE 53 struct __declspec(empty_bases) basic_tuple_impl<std::index_sequence<n...>, Xn...> 54 #else 55 struct basic_tuple_impl<std::index_sequence<n...>, Xn...> 56 #endif 57 : detail::ebo<bti<n>, Xn>... 58 { 59 static constexpr std::size_t size_ = sizeof...(Xn); 60 61 constexpr basic_tuple_impl() = default; 62 63 template <typename Other> basic_tuple_impldetail::basic_tuple_impl64 explicit constexpr basic_tuple_impl(detail::from_other, Other&& other) 65 : detail::ebo<bti<n>, Xn>(detail::ebo_get<bti<n>>(static_cast<Other&&>(other)))... 66 { } 67 68 template <typename ...Yn> basic_tuple_impldetail::basic_tuple_impl69 explicit constexpr basic_tuple_impl(Yn&& ...yn) 70 : detail::ebo<bti<n>, Xn>(static_cast<Yn&&>(yn))... 71 { } 72 }; 73 } 74 75 ////////////////////////////////////////////////////////////////////////// 76 // basic_tuple 77 ////////////////////////////////////////////////////////////////////////// 78 //! @cond 79 template <typename ...Xn> 80 struct basic_tuple final 81 : detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...> 82 { 83 using Base = detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>; 84 85 constexpr basic_tuple() = default; 86 87 // copy constructor 88 template <typename Other, typename = typename std::enable_if< 89 std::is_same<typename detail::decay<Other>::type, basic_tuple>::value 90 >::type> basic_tuplebasic_tuple91 constexpr basic_tuple(Other&& other) 92 : Base(detail::from_other{}, static_cast<Other&&>(other)) 93 { } 94 95 template <typename ...Yn> basic_tuplebasic_tuple96 explicit constexpr basic_tuple(Yn&& ...yn) 97 : Base(static_cast<Yn&&>(yn)...) 98 { } 99 }; 100 //! @endcond 101 102 template <typename ...Xn> 103 struct tag_of<basic_tuple<Xn...>> { 104 using type = basic_tuple_tag; 105 }; 106 107 ////////////////////////////////////////////////////////////////////////// 108 // Foldable 109 ////////////////////////////////////////////////////////////////////////// 110 template <> 111 struct unpack_impl<basic_tuple_tag> { 112 template <std::size_t ...i, typename ...Xn, typename F> 113 static constexpr decltype(auto) applyunpack_impl114 apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F&& f) { 115 return static_cast<F&&>(f)( 116 detail::ebo_get<detail::bti<i>>( 117 static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs) 118 )... 119 ); 120 } 121 122 template <std::size_t ...i, typename ...Xn, typename F> 123 static constexpr decltype(auto) applyunpack_impl124 apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F&& f) { 125 return static_cast<F&&>(f)( 126 detail::ebo_get<detail::bti<i>>( 127 static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs) 128 )... 129 ); 130 } 131 132 template <std::size_t ...i, typename ...Xn, typename F> 133 static constexpr decltype(auto) applyunpack_impl134 apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F&& f) { 135 return static_cast<F&&>(f)( 136 detail::ebo_get<detail::bti<i>>( 137 static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs) 138 )... 139 ); 140 } 141 }; 142 143 ////////////////////////////////////////////////////////////////////////// 144 // Functor 145 ////////////////////////////////////////////////////////////////////////// 146 template <> 147 struct transform_impl<basic_tuple_tag> { 148 template <std::size_t ...i, typename ...Xn, typename F> 149 static constexpr auto applytransform_impl150 apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F const& f) { 151 return hana::make_basic_tuple( 152 f(detail::ebo_get<detail::bti<i>>( 153 static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs) 154 ))... 155 ); 156 } 157 158 template <std::size_t ...i, typename ...Xn, typename F> 159 static constexpr auto applytransform_impl160 apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F const& f) { 161 return hana::make_basic_tuple( 162 f(detail::ebo_get<detail::bti<i>>( 163 static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs) 164 ))... 165 ); 166 } 167 168 template <std::size_t ...i, typename ...Xn, typename F> 169 static constexpr auto applytransform_impl170 apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F const& f) { 171 return hana::make_basic_tuple( 172 f(detail::ebo_get<detail::bti<i>>( 173 static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs) 174 ))... 175 ); 176 } 177 }; 178 179 ////////////////////////////////////////////////////////////////////////// 180 // Iterable 181 ////////////////////////////////////////////////////////////////////////// 182 template <> 183 struct at_impl<basic_tuple_tag> { 184 template <typename Xs, typename N> applyat_impl185 static constexpr decltype(auto) apply(Xs&& xs, N const&) { 186 constexpr std::size_t index = N::value; 187 return detail::ebo_get<detail::bti<index>>(static_cast<Xs&&>(xs)); 188 } 189 }; 190 191 template <> 192 struct drop_front_impl<basic_tuple_tag> { 193 template <std::size_t N, typename Xs, std::size_t ...i> drop_front_helperdrop_front_impl194 static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) { 195 return hana::make_basic_tuple( 196 detail::ebo_get<detail::bti<i+N>>(static_cast<Xs&&>(xs))... 197 ); 198 } 199 200 template <typename Xs, typename N> applydrop_front_impl201 static constexpr auto apply(Xs&& xs, N const&) { 202 constexpr std::size_t len = detail::decay<Xs>::type::size_; 203 return drop_front_helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence< 204 (N::value < len) ? len - N::value : 0 205 >{}); 206 } 207 }; 208 209 template <> 210 struct is_empty_impl<basic_tuple_tag> { 211 template <typename ...Xs> 212 static constexpr hana::bool_<sizeof...(Xs) == 0> applyis_empty_impl213 apply(basic_tuple<Xs...> const&) 214 { return {}; } 215 }; 216 217 // compile-time optimizations (to reduce the # of function instantiations) 218 template <std::size_t n, typename ...Xs> at_c(basic_tuple<Xs...> const & xs)219 constexpr decltype(auto) at_c(basic_tuple<Xs...> const& xs) { 220 return detail::ebo_get<detail::bti<n>>(xs); 221 } 222 223 template <std::size_t n, typename ...Xs> at_c(basic_tuple<Xs...> & xs)224 constexpr decltype(auto) at_c(basic_tuple<Xs...>& xs) { 225 return detail::ebo_get<detail::bti<n>>(xs); 226 } 227 228 template <std::size_t n, typename ...Xs> at_c(basic_tuple<Xs...> && xs)229 constexpr decltype(auto) at_c(basic_tuple<Xs...>&& xs) { 230 return detail::ebo_get<detail::bti<n>>(static_cast<basic_tuple<Xs...>&&>(xs)); 231 } 232 233 ////////////////////////////////////////////////////////////////////////// 234 // Sequence 235 ////////////////////////////////////////////////////////////////////////// 236 template <> 237 struct Sequence<basic_tuple_tag> { 238 static constexpr bool value = true; 239 }; 240 241 template <> 242 struct make_impl<basic_tuple_tag> { 243 template <typename ...Xn> 244 static constexpr basic_tuple<typename detail::decay<Xn>::type...> applymake_impl245 apply(Xn&& ...xn) { 246 return basic_tuple<typename detail::decay<Xn>::type...>{ 247 static_cast<Xn&&>(xn)... 248 }; 249 } 250 }; 251 252 ////////////////////////////////////////////////////////////////////////// 253 // length 254 ////////////////////////////////////////////////////////////////////////// 255 template <> 256 struct length_impl<basic_tuple_tag> { 257 template <typename ...Xn> applylength_impl258 static constexpr auto apply(basic_tuple<Xn...> const&) { 259 return hana::size_t<sizeof...(Xn)>{}; 260 } 261 }; 262 BOOST_HANA_NAMESPACE_END 263 264 #endif // !BOOST_HANA_BASIC_TUPLE_HPP 265