• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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