/*! @file Defines `boost::hana::basic_tuple`. Copyright Louis Dionne 2013-2022 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_HANA_BASIC_TUPLE_HPP #define BOOST_HANA_BASIC_TUPLE_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace hana { namespace detail { ////////////////////////////////////////////////////////////////////// // basic_tuple_impl ////////////////////////////////////////////////////////////////////// template struct bti; // basic_tuple_index struct from_other { }; template #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE struct __declspec(empty_bases) basic_tuple_impl; #else struct basic_tuple_impl; #endif template #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE struct __declspec(empty_bases) basic_tuple_impl, Xn...> #else struct basic_tuple_impl, Xn...> #endif : detail::ebo, Xn>... { static constexpr std::size_t size_ = sizeof...(Xn); constexpr basic_tuple_impl() = default; template explicit constexpr basic_tuple_impl(detail::from_other, Other&& other) : detail::ebo, Xn>(detail::ebo_get>(static_cast(other)))... { } template explicit constexpr basic_tuple_impl(Yn&& ...yn) : detail::ebo, Xn>(static_cast(yn))... { } }; } ////////////////////////////////////////////////////////////////////////// // basic_tuple ////////////////////////////////////////////////////////////////////////// //! @cond template struct basic_tuple final : detail::basic_tuple_impl, Xn...> { using Base = detail::basic_tuple_impl, Xn...>; constexpr basic_tuple() = default; // copy constructor template ::type, basic_tuple>::value >::type> constexpr basic_tuple(Other&& other) : Base(detail::from_other{}, static_cast(other)) { } template explicit constexpr basic_tuple(Yn&& ...yn) : Base(static_cast(yn)...) { } }; //! @endcond template struct tag_of> { using type = basic_tuple_tag; }; ////////////////////////////////////////////////////////////////////////// // Foldable ////////////////////////////////////////////////////////////////////////// template <> struct unpack_impl { template static constexpr decltype(auto) apply(detail::basic_tuple_impl, Xn...> const& xs, F&& f) { return static_cast(f)( detail::ebo_get>( static_cast, Xn> const&>(xs) )... ); } template static constexpr decltype(auto) apply(detail::basic_tuple_impl, Xn...>& xs, F&& f) { return static_cast(f)( detail::ebo_get>( static_cast, Xn>&>(xs) )... ); } template static constexpr decltype(auto) apply(detail::basic_tuple_impl, Xn...>&& xs, F&& f) { return static_cast(f)( detail::ebo_get>( static_cast, Xn>&&>(xs) )... ); } }; ////////////////////////////////////////////////////////////////////////// // Functor ////////////////////////////////////////////////////////////////////////// template <> struct transform_impl { template static constexpr auto apply(detail::basic_tuple_impl, Xn...> const& xs, F const& f) { return hana::make_basic_tuple( f(detail::ebo_get>( static_cast, Xn> const&>(xs) ))... ); } template static constexpr auto apply(detail::basic_tuple_impl, Xn...>& xs, F const& f) { return hana::make_basic_tuple( f(detail::ebo_get>( static_cast, Xn>&>(xs) ))... ); } template static constexpr auto apply(detail::basic_tuple_impl, Xn...>&& xs, F const& f) { return hana::make_basic_tuple( f(detail::ebo_get>( static_cast, Xn>&&>(xs) ))... ); } }; ////////////////////////////////////////////////////////////////////////// // Iterable ////////////////////////////////////////////////////////////////////////// template <> struct at_impl { template static constexpr decltype(auto) apply(Xs&& xs, N const&) { constexpr std::size_t index = N::value; return detail::ebo_get>(static_cast(xs)); } }; template <> struct drop_front_impl { template static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence) { return hana::make_basic_tuple( detail::ebo_get>(static_cast(xs))... ); } template static constexpr auto apply(Xs&& xs, N const&) { constexpr std::size_t len = detail::decay::type::size_; return drop_front_helper(static_cast(xs), std::make_index_sequence< (N::value < len) ? len - N::value : 0 >{}); } }; template <> struct is_empty_impl { template static constexpr hana::bool_ apply(basic_tuple const&) { return {}; } }; // compile-time optimizations (to reduce the # of function instantiations) template constexpr decltype(auto) at_c(basic_tuple const& xs) { return detail::ebo_get>(xs); } template constexpr decltype(auto) at_c(basic_tuple& xs) { return detail::ebo_get>(xs); } template constexpr decltype(auto) at_c(basic_tuple&& xs) { return detail::ebo_get>(static_cast&&>(xs)); } ////////////////////////////////////////////////////////////////////////// // Sequence ////////////////////////////////////////////////////////////////////////// template <> struct Sequence { static constexpr bool value = true; }; template <> struct make_impl { template static constexpr basic_tuple::type...> apply(Xn&& ...xn) { return basic_tuple::type...>{ static_cast(xn)... }; } }; ////////////////////////////////////////////////////////////////////////// // length ////////////////////////////////////////////////////////////////////////// template <> struct length_impl { template static constexpr auto apply(basic_tuple const&) { return hana::size_t{}; } }; }} // end namespace boost::hana #endif // !BOOST_HANA_BASIC_TUPLE_HPP