/*! @file Defines `boost::hana::basic_tuple`. @copyright Louis Dionne 2013-2016 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 #if 0 //! @todo Until we strip down headers, this includes too much #include #include #endif #include #include #include BOOST_HANA_NAMESPACE_BEGIN namespace detail { ////////////////////////////////////////////////////////////////////// // elt // // `elt` stands for `tuple_element`; the name is compressed to reduce // symbol lengths. // // Wrapper holding the actual elements of a tuple. It takes care of // optimizing the storage for empty types. // // When available, we use compiler intrinsics to reduce the number // of instantiations. ////////////////////////////////////////////////////////////////////// template struct elt; // Specialize storage for empty types template struct elt : Xn { constexpr elt() = default; template explicit constexpr elt(Yn&& yn) : Xn(static_cast(yn)) { } }; // Specialize storage for non-empty types template struct elt { constexpr elt() = default; template explicit constexpr elt(Yn&& yn) : data_(static_cast(yn)) { } Xn data_; }; } ////////////////////////////////////////////////////////////////////////// // get_impl ////////////////////////////////////////////////////////////////////////// template constexpr Xn const& get_impl(detail::elt const& xn) { return xn; } template constexpr Xn& get_impl(detail::elt& xn) { return xn; } template constexpr Xn&& get_impl(detail::elt&& xn) { return static_cast(xn); } template constexpr Xn const& get_impl(detail::elt const& xn) { return xn.data_; } template constexpr Xn& get_impl(detail::elt& xn) { return xn.data_; } template constexpr Xn&& get_impl(detail::elt&& xn) { return static_cast(xn.data_); } namespace detail { ////////////////////////////////////////////////////////////////////// // basic_tuple_impl ////////////////////////////////////////////////////////////////////// struct from_other { }; template struct basic_tuple_impl; template struct basic_tuple_impl, Xn...> : detail::elt... { 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::elt(get_impl(static_cast(other)))... { } template explicit constexpr basic_tuple_impl(Yn&& ...yn) : detail::elt(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)( get_impl(static_cast const&>(xs))... ); } template static constexpr decltype(auto) apply(detail::basic_tuple_impl, Xn...>& xs, F&& f) { return static_cast(f)( get_impl(static_cast&>(xs))... ); } template static constexpr decltype(auto) apply(detail::basic_tuple_impl, Xn...>&& xs, F&& f) { return static_cast(f)( get_impl(static_cast&&>(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(get_impl(static_cast const&>(xs)))... ); } template static constexpr auto apply(detail::basic_tuple_impl, Xn...>& xs, F const& f) { return hana::make_basic_tuple( f(get_impl(static_cast&>(xs)))... ); } template static constexpr auto apply(detail::basic_tuple_impl, Xn...>&& xs, F const& f) { return hana::make_basic_tuple( f(get_impl(static_cast&&>(xs)))... ); } }; ////////////////////////////////////////////////////////////////////////// // Iterable ////////////////////////////////////////////////////////////////////////// template <> struct at_impl { template static constexpr decltype(auto) apply(Xs&& xs, N const&) { constexpr std::size_t index = N::value; return hana::get_impl(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(hana::get_impl(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 {}; } }; ////////////////////////////////////////////////////////////////////////// // 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)... }; } }; #if 0 ////////////////////////////////////////////////////////////////////////// // length ////////////////////////////////////////////////////////////////////////// template <> struct length_impl { template static constexpr auto apply(basic_tuple const&) { return hana::size_c; } }; #endif BOOST_HANA_NAMESPACE_END #endif // !BOOST_HANA_BASIC_TUPLE_HPP