3 Defines `boost::hana::tuple`.
5 @copyright Louis Dionne 2013-2017
6 @copyright Jason Rice 2017
7 Distributed under the Boost Software License, Version 1.0.
8 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
11 #ifndef BOOST_HANA_TUPLE_HPP
12 #define BOOST_HANA_TUPLE_HPP
14 #include <boost/hana/fwd/tuple.hpp>
16 #include <boost/hana/basic_tuple.hpp>
17 #include <boost/hana/bool.hpp>
18 #include <boost/hana/config.hpp>
19 #include <boost/hana/detail/decay.hpp>
20 #include <boost/hana/detail/fast_and.hpp>
21 #include <boost/hana/detail/index_if.hpp>
22 #include <boost/hana/detail/intrinsics.hpp>
23 #include <boost/hana/detail/operators/adl.hpp>
24 #include <boost/hana/detail/operators/comparable.hpp>
25 #include <boost/hana/detail/operators/iterable.hpp>
26 #include <boost/hana/detail/operators/monad.hpp>
27 #include <boost/hana/detail/operators/orderable.hpp>
28 #include <boost/hana/fwd/at.hpp>
29 #include <boost/hana/fwd/core/make.hpp>
30 #include <boost/hana/fwd/drop_front.hpp>
31 #include <boost/hana/fwd/index_if.hpp>
32 #include <boost/hana/fwd/is_empty.hpp>
33 #include <boost/hana/fwd/length.hpp>
34 #include <boost/hana/fwd/optional.hpp>
35 #include <boost/hana/fwd/unpack.hpp>
36 #include <boost/hana/type.hpp> // required by fwd decl of tuple_t
39 #include <type_traits>
43 BOOST_HANA_NAMESPACE_BEGIN
45 template <typename Xs, typename Ys, std::size_t ...n>
46 constexpr void assign(Xs& xs, Ys&& ys, std::index_sequence<n...>) {
47 int sequence[] = {int{}, ((void)(
48 hana::at_c<n>(xs) = hana::at_c<n>(static_cast<Ys&&>(ys))
53 struct from_index_sequence_t { };
55 template <typename Tuple, typename ...Yn>
56 struct is_same_tuple : std::false_type { };
58 template <typename Tuple>
59 struct is_same_tuple<typename detail::decay<Tuple>::type, Tuple>
63 template <bool SameTuple, bool SameNumberOfElements, typename Tuple, typename ...Yn>
64 struct enable_tuple_variadic_ctor;
66 template <typename ...Xn, typename ...Yn>
67 struct enable_tuple_variadic_ctor<false, true, hana::tuple<Xn...>, Yn...>
69 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
74 //////////////////////////////////////////////////////////////////////////
76 //////////////////////////////////////////////////////////////////////////
78 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
79 struct __declspec(empty_bases) tuple<> final
83 : detail::operators::adl<tuple<>>
84 , detail::iterable_operators<tuple<>>
87 using hana_tag = tuple_tag;
90 template <typename ...Xn>
91 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
92 struct __declspec(empty_bases) tuple final
96 : detail::operators::adl<tuple<Xn...>>
97 , detail::iterable_operators<tuple<Xn...>>
99 basic_tuple<Xn...> storage_;
100 using hana_tag = tuple_tag;
103 template <typename Other, std::size_t ...n>
104 explicit constexpr tuple(detail::from_index_sequence_t, std::index_sequence<n...>, Other&& other)
105 : storage_(hana::at_c<n>(static_cast<Other&&>(other))...)
109 template <typename ...dummy, typename = typename std::enable_if<
110 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, dummy...)...>::value
116 template <typename ...dummy, typename = typename std::enable_if<
117 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
119 constexpr tuple(Xn const& ...xn)
123 template <typename ...Yn, typename = typename detail::enable_tuple_variadic_ctor<
124 detail::is_same_tuple<tuple, Yn...>::value,
125 sizeof...(Xn) == sizeof...(Yn), tuple, Yn...
127 constexpr tuple(Yn&& ...yn)
128 : storage_(static_cast<Yn&&>(yn)...)
131 template <typename ...Yn, typename = typename std::enable_if<
132 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn const&)...>::value
134 constexpr tuple(tuple<Yn...> const& other)
135 : tuple(detail::from_index_sequence_t{},
136 std::make_index_sequence<sizeof...(Xn)>{},
140 template <typename ...Yn, typename = typename std::enable_if<
141 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
143 constexpr tuple(tuple<Yn...>&& other)
144 : tuple(detail::from_index_sequence_t{},
145 std::make_index_sequence<sizeof...(Xn)>{},
146 static_cast<tuple<Yn...>&&>(other).storage_)
149 // The three following constructors are required to make sure that
150 // the tuple(Yn&&...) constructor is _not_ preferred over the copy
151 // constructor for unary tuples containing a type that is constructible
152 // from tuple<...>. See test/tuple/cnstr.trap.cpp
153 template <typename ...dummy, typename = typename std::enable_if<
154 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
156 constexpr tuple(tuple const& other)
157 : tuple(detail::from_index_sequence_t{},
158 std::make_index_sequence<sizeof...(Xn)>{},
162 template <typename ...dummy, typename = typename std::enable_if<
163 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
165 constexpr tuple(tuple& other)
166 : tuple(const_cast<tuple const&>(other))
169 template <typename ...dummy, typename = typename std::enable_if<
170 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn&&, dummy...)...>::value
172 constexpr tuple(tuple&& other)
173 : tuple(detail::from_index_sequence_t{},
174 std::make_index_sequence<sizeof...(Xn)>{},
175 static_cast<tuple&&>(other).storage_)
179 template <typename ...Yn, typename = typename std::enable_if<
180 detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn const&)...>::value
182 constexpr tuple& operator=(tuple<Yn...> const& other) {
183 detail::assign(this->storage_, other.storage_,
184 std::make_index_sequence<sizeof...(Xn)>{});
188 template <typename ...Yn, typename = typename std::enable_if<
189 detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn&&)...>::value
191 constexpr tuple& operator=(tuple<Yn...>&& other) {
192 detail::assign(this->storage_, static_cast<tuple<Yn...>&&>(other).storage_,
193 std::make_index_sequence<sizeof...(Xn)>{});
198 //////////////////////////////////////////////////////////////////////////
200 //////////////////////////////////////////////////////////////////////////
203 struct comparable_operators<tuple_tag> {
204 static constexpr bool value = true;
207 struct orderable_operators<tuple_tag> {
208 static constexpr bool value = true;
211 struct monad_operators<tuple_tag> {
212 static constexpr bool value = true;
216 //////////////////////////////////////////////////////////////////////////
218 //////////////////////////////////////////////////////////////////////////
220 struct unpack_impl<tuple_tag> {
221 template <typename F>
222 static constexpr decltype(auto) apply(tuple<>&&, F&& f)
223 { return static_cast<F&&>(f)(); }
224 template <typename F>
225 static constexpr decltype(auto) apply(tuple<>&, F&& f)
226 { return static_cast<F&&>(f)(); }
227 template <typename F>
228 static constexpr decltype(auto) apply(tuple<> const&, F&& f)
229 { return static_cast<F&&>(f)(); }
231 template <typename Xs, typename F>
232 static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
233 return hana::unpack(static_cast<Xs&&>(xs).storage_, static_cast<F&&>(f));
238 struct length_impl<tuple_tag> {
239 template <typename ...Xs>
240 static constexpr auto apply(tuple<Xs...> const&)
241 { return hana::size_c<sizeof...(Xs)>; }
244 //////////////////////////////////////////////////////////////////////////
246 //////////////////////////////////////////////////////////////////////////
248 struct at_impl<tuple_tag> {
249 template <typename Xs, typename N>
250 static constexpr decltype(auto) apply(Xs&& xs, N const&) {
251 constexpr std::size_t index = N::value;
252 return hana::at_c<index>(static_cast<Xs&&>(xs).storage_);
257 struct drop_front_impl<tuple_tag> {
258 template <std::size_t N, typename Xs, std::size_t ...i>
259 static constexpr auto helper(Xs&& xs, std::index_sequence<i...>) {
260 return hana::make<tuple_tag>(hana::at_c<i+N>(static_cast<Xs&&>(xs))...);
263 template <typename Xs, typename N>
264 static constexpr auto apply(Xs&& xs, N const&) {
265 constexpr std::size_t len = decltype(hana::length(xs))::value;
266 return helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence<
267 (N::value < len) ? len - N::value : 0
273 struct is_empty_impl<tuple_tag> {
274 template <typename ...Xs>
275 static constexpr auto apply(tuple<Xs...> const&)
276 { return hana::bool_c<sizeof...(Xs) == 0>; }
279 // compile-time optimizations (to reduce the # of function instantiations)
280 template <std::size_t n, typename ...Xs>
281 constexpr decltype(auto) at_c(tuple<Xs...> const& xs) {
282 return hana::at_c<n>(xs.storage_);
285 template <std::size_t n, typename ...Xs>
286 constexpr decltype(auto) at_c(tuple<Xs...>& xs) {
287 return hana::at_c<n>(xs.storage_);
290 template <std::size_t n, typename ...Xs>
291 constexpr decltype(auto) at_c(tuple<Xs...>&& xs) {
292 return hana::at_c<n>(static_cast<tuple<Xs...>&&>(xs).storage_);
296 struct index_if_impl<tuple_tag> {
297 template <typename ...Xs, typename Pred>
298 static constexpr auto apply(tuple<Xs...> const&, Pred const&)
299 -> typename detail::index_if<Pred, Xs...>::type
303 //////////////////////////////////////////////////////////////////////////
305 //////////////////////////////////////////////////////////////////////////
307 struct Sequence<tuple_tag> {
308 static constexpr bool value = true;
312 struct make_impl<tuple_tag> {
313 template <typename ...Xs>
315 tuple<typename detail::decay<Xs>::type...> apply(Xs&& ...xs)
316 { return {static_cast<Xs&&>(xs)...}; }
318 BOOST_HANA_NAMESPACE_END
320 #endif // !BOOST_HANA_TUPLE_HPP