File indexing completed on 2024-11-15 09:13:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_HANA_TUPLE_HPP
0012 #define BOOST_HANA_TUPLE_HPP
0013
0014 #include <boost/hana/fwd/tuple.hpp>
0015
0016 #include <boost/hana/basic_tuple.hpp>
0017 #include <boost/hana/bool.hpp>
0018 #include <boost/hana/config.hpp>
0019 #include <boost/hana/detail/decay.hpp>
0020 #include <boost/hana/detail/fast_and.hpp>
0021 #include <boost/hana/detail/index_if.hpp>
0022 #include <boost/hana/detail/intrinsics.hpp>
0023 #include <boost/hana/detail/operators/adl.hpp>
0024 #include <boost/hana/detail/operators/comparable.hpp>
0025 #include <boost/hana/detail/operators/iterable.hpp>
0026 #include <boost/hana/detail/operators/monad.hpp>
0027 #include <boost/hana/detail/operators/orderable.hpp>
0028 #include <boost/hana/fwd/at.hpp>
0029 #include <boost/hana/fwd/core/make.hpp>
0030 #include <boost/hana/fwd/drop_front.hpp>
0031 #include <boost/hana/fwd/index_if.hpp>
0032 #include <boost/hana/fwd/is_empty.hpp>
0033 #include <boost/hana/fwd/length.hpp>
0034 #include <boost/hana/fwd/optional.hpp>
0035 #include <boost/hana/fwd/unpack.hpp>
0036 #include <boost/hana/type.hpp> // required by fwd decl of tuple_t
0037
0038 #include <cstddef>
0039 #include <type_traits>
0040 #include <utility>
0041
0042
0043 namespace boost { namespace hana {
0044 namespace detail {
0045 template <typename Xs, typename Ys, std::size_t ...n>
0046 constexpr void assign(Xs& xs, Ys&& ys, std::index_sequence<n...>) {
0047 int sequence[] = {int{}, ((void)(
0048 hana::at_c<n>(xs) = hana::at_c<n>(static_cast<Ys&&>(ys))
0049 ), int{})...};
0050 (void)sequence;
0051 }
0052
0053 struct from_index_sequence_t { };
0054
0055 template <typename Tuple, typename ...Yn>
0056 struct is_same_tuple : std::false_type { };
0057
0058 template <typename Tuple>
0059 struct is_same_tuple<typename detail::decay<Tuple>::type, Tuple>
0060 : std::true_type
0061 { };
0062
0063 template <bool SameTuple, bool SameNumberOfElements, typename Tuple, typename ...Yn>
0064 struct enable_tuple_variadic_ctor;
0065
0066 template <typename ...Xn, typename ...Yn>
0067 struct enable_tuple_variadic_ctor<false, true, hana::tuple<Xn...>, Yn...>
0068 : std::enable_if<
0069 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
0070 >
0071 { };
0072 }
0073
0074
0075
0076
0077 template <>
0078 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
0079 struct __declspec(empty_bases) tuple<> final
0080 #else
0081 struct tuple<> final
0082 #endif
0083 : detail::operators::adl<tuple<>>
0084 , detail::iterable_operators<tuple<>>
0085 {
0086 constexpr tuple() { }
0087 using hana_tag = tuple_tag;
0088 };
0089
0090 template <typename ...Xn>
0091 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
0092 struct __declspec(empty_bases) tuple final
0093 #else
0094 struct tuple final
0095 #endif
0096 : detail::operators::adl<tuple<Xn...>>
0097 , detail::iterable_operators<tuple<Xn...>>
0098 {
0099 basic_tuple<Xn...> storage_;
0100 using hana_tag = tuple_tag;
0101
0102 private:
0103 template <typename Other, std::size_t ...n>
0104 explicit constexpr tuple(detail::from_index_sequence_t, std::index_sequence<n...>, Other&& other)
0105 : storage_(hana::at_c<n>(static_cast<Other&&>(other))...)
0106 { }
0107
0108 public:
0109 template <typename ...dummy, typename = typename std::enable_if<
0110 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, dummy...)...>::value
0111 >::type>
0112 constexpr tuple()
0113 : storage_()
0114 { }
0115
0116 template <typename ...dummy, typename = typename std::enable_if<
0117 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
0118 >::type>
0119 constexpr tuple(Xn const& ...xn)
0120 : storage_(xn...)
0121 { }
0122
0123 template <typename ...Yn, typename = typename detail::enable_tuple_variadic_ctor<
0124 detail::is_same_tuple<tuple, Yn...>::value,
0125 sizeof...(Xn) == sizeof...(Yn), tuple, Yn...
0126 >::type>
0127 constexpr tuple(Yn&& ...yn)
0128 : storage_(static_cast<Yn&&>(yn)...)
0129 { }
0130
0131 template <typename ...Yn, typename = typename std::enable_if<
0132 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn const&)...>::value
0133 >::type>
0134 constexpr tuple(tuple<Yn...> const& other)
0135 : tuple(detail::from_index_sequence_t{},
0136 std::make_index_sequence<sizeof...(Xn)>{},
0137 other.storage_)
0138 { }
0139
0140 template <typename ...Yn, typename = typename std::enable_if<
0141 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Yn&&)...>::value
0142 >::type>
0143 constexpr tuple(tuple<Yn...>&& other)
0144 : tuple(detail::from_index_sequence_t{},
0145 std::make_index_sequence<sizeof...(Xn)>{},
0146 static_cast<tuple<Yn...>&&>(other).storage_)
0147 { }
0148
0149
0150
0151
0152
0153 template <typename ...dummy, typename = typename std::enable_if<
0154 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
0155 >::type>
0156 constexpr tuple(tuple const& other)
0157 : tuple(detail::from_index_sequence_t{},
0158 std::make_index_sequence<sizeof...(Xn)>{},
0159 other.storage_)
0160 { }
0161
0162 template <typename ...dummy, typename = typename std::enable_if<
0163 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn const&, dummy...)...>::value
0164 >::type>
0165 constexpr tuple(tuple& other)
0166 : tuple(const_cast<tuple const&>(other))
0167 { }
0168
0169 template <typename ...dummy, typename = typename std::enable_if<
0170 detail::fast_and<BOOST_HANA_TT_IS_CONSTRUCTIBLE(Xn, Xn&&, dummy...)...>::value
0171 >::type>
0172 constexpr tuple(tuple&& other)
0173 : tuple(detail::from_index_sequence_t{},
0174 std::make_index_sequence<sizeof...(Xn)>{},
0175 static_cast<tuple&&>(other).storage_)
0176 { }
0177
0178
0179 template <typename ...Yn, typename = typename std::enable_if<
0180 detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn const&)...>::value
0181 >::type>
0182 constexpr tuple& operator=(tuple<Yn...> const& other) {
0183 detail::assign(this->storage_, other.storage_,
0184 std::make_index_sequence<sizeof...(Xn)>{});
0185 return *this;
0186 }
0187
0188 template <typename ...Yn, typename = typename std::enable_if<
0189 detail::fast_and<BOOST_HANA_TT_IS_ASSIGNABLE(Xn&, Yn&&)...>::value
0190 >::type>
0191 constexpr tuple& operator=(tuple<Yn...>&& other) {
0192 detail::assign(this->storage_, static_cast<tuple<Yn...>&&>(other).storage_,
0193 std::make_index_sequence<sizeof...(Xn)>{});
0194 return *this;
0195 }
0196 };
0197
0198
0199
0200
0201 namespace detail {
0202 template <>
0203 struct comparable_operators<tuple_tag> {
0204 static constexpr bool value = true;
0205 };
0206 template <>
0207 struct orderable_operators<tuple_tag> {
0208 static constexpr bool value = true;
0209 };
0210 template <>
0211 struct monad_operators<tuple_tag> {
0212 static constexpr bool value = true;
0213 };
0214 }
0215
0216
0217
0218
0219 template <>
0220 struct unpack_impl<tuple_tag> {
0221 template <typename F>
0222 static constexpr decltype(auto) apply(tuple<>&&, F&& f)
0223 { return static_cast<F&&>(f)(); }
0224 template <typename F>
0225 static constexpr decltype(auto) apply(tuple<>&, F&& f)
0226 { return static_cast<F&&>(f)(); }
0227 template <typename F>
0228 static constexpr decltype(auto) apply(tuple<> const&, F&& f)
0229 { return static_cast<F&&>(f)(); }
0230
0231 template <typename Xs, typename F>
0232 static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
0233 return hana::unpack(static_cast<Xs&&>(xs).storage_, static_cast<F&&>(f));
0234 }
0235 };
0236
0237 template <>
0238 struct length_impl<tuple_tag> {
0239 template <typename ...Xs>
0240 static constexpr auto apply(tuple<Xs...> const&)
0241 { return hana::size_c<sizeof...(Xs)>; }
0242 };
0243
0244
0245
0246
0247 template <>
0248 struct at_impl<tuple_tag> {
0249 template <typename Xs, typename N>
0250 static constexpr decltype(auto) apply(Xs&& xs, N const&) {
0251 constexpr std::size_t index = N::value;
0252 return hana::at_c<index>(static_cast<Xs&&>(xs).storage_);
0253 }
0254 };
0255
0256 template <>
0257 struct drop_front_impl<tuple_tag> {
0258 template <std::size_t N, typename Xs, std::size_t ...i>
0259 static constexpr auto helper(Xs&& xs, std::index_sequence<i...>) {
0260 return hana::make<tuple_tag>(hana::at_c<i+N>(static_cast<Xs&&>(xs))...);
0261 }
0262
0263 template <typename Xs, typename N>
0264 static constexpr auto apply(Xs&& xs, N const&) {
0265 constexpr std::size_t len = decltype(hana::length(xs))::value;
0266 return helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence<
0267 (N::value < len) ? len - N::value : 0
0268 >{});
0269 }
0270 };
0271
0272 template <>
0273 struct is_empty_impl<tuple_tag> {
0274 template <typename ...Xs>
0275 static constexpr auto apply(tuple<Xs...> const&)
0276 { return hana::bool_c<sizeof...(Xs) == 0>; }
0277 };
0278
0279
0280 template <std::size_t n, typename ...Xs>
0281 constexpr decltype(auto) at_c(tuple<Xs...> const& xs) {
0282 return hana::at_c<n>(xs.storage_);
0283 }
0284
0285 template <std::size_t n, typename ...Xs>
0286 constexpr decltype(auto) at_c(tuple<Xs...>& xs) {
0287 return hana::at_c<n>(xs.storage_);
0288 }
0289
0290 template <std::size_t n, typename ...Xs>
0291 constexpr decltype(auto) at_c(tuple<Xs...>&& xs) {
0292 return hana::at_c<n>(static_cast<tuple<Xs...>&&>(xs).storage_);
0293 }
0294
0295 template <>
0296 struct index_if_impl<tuple_tag> {
0297 template <typename ...Xs, typename Pred>
0298 static constexpr auto apply(tuple<Xs...> const&, Pred const&)
0299 -> typename detail::index_if<Pred, Xs...>::type
0300 { return {}; }
0301 };
0302
0303
0304
0305
0306 template <>
0307 struct Sequence<tuple_tag> {
0308 static constexpr bool value = true;
0309 };
0310
0311 template <>
0312 struct make_impl<tuple_tag> {
0313 template <typename ...Xs>
0314 static constexpr
0315 tuple<typename detail::decay<Xs>::type...> apply(Xs&& ...xs)
0316 { return {static_cast<Xs&&>(xs)...}; }
0317 };
0318 }}
0319
0320 #endif