/*! @file Adapts `std::tuple` for use with Hana. @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_EXT_STD_TUPLE_HPP #define BOOST_HANA_EXT_STD_TUPLE_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef BOOST_HANA_CONFIG_HAS_NO_STD_TUPLE_ADAPTER # error The adapter for std::tuple is not supported with versions of \ libc++ prior to the one shipped with Clang 3.7 because of a bug \ in the tuple implementation. #endif #ifdef BOOST_HANA_DOXYGEN_INVOKED namespace std { //! @ingroup group-ext-std //! Adapter for `std::tuple`s. //! //! //! Modeled concepts //! ---------------- //! A `std::tuple` is a model of the `Sequence` concept, and all the //! concepts it refines. That makes it essentially the same as a Hana //! tuple, although the complexity of some operations might differ from //! that of Hana's tuple. //! //! @include example/ext/std/tuple.cpp template struct tuple { }; } #endif BOOST_HANA_NAMESPACE_BEGIN namespace ext { namespace std { struct tuple_tag; }} template struct tag_of> { using type = ext::std::tuple_tag; }; ////////////////////////////////////////////////////////////////////////// // make ////////////////////////////////////////////////////////////////////////// template <> struct make_impl { template static constexpr decltype(auto) apply(Xs&& ...xs) { return std::make_tuple(static_cast(xs)...); } }; ////////////////////////////////////////////////////////////////////////// // Applicative ////////////////////////////////////////////////////////////////////////// template <> struct lift_impl { template static constexpr auto apply(X&& x) { return std::tuple::type>{ static_cast(x)}; } }; ////////////////////////////////////////////////////////////////////////// // Monad ////////////////////////////////////////////////////////////////////////// template <> struct flatten_impl { template static constexpr decltype(auto) flatten_helper(Xs&& xs, std::index_sequence) { #if defined(BOOST_HANA_CONFIG_LIBCPP_HAS_BUG_22806) return std::tuple_cat(std::get(xs)...); #else return std::tuple_cat(std::get(static_cast(xs))...); #endif } template static constexpr decltype(auto) apply(Xs&& xs) { using Raw = typename std::remove_reference::type; constexpr std::size_t Length = std::tuple_size::value; return flatten_helper(static_cast(xs), std::make_index_sequence{}); } }; ////////////////////////////////////////////////////////////////////////// // MonadPlus ////////////////////////////////////////////////////////////////////////// template <> struct empty_impl { static constexpr auto apply() { return std::tuple<>{}; } }; ////////////////////////////////////////////////////////////////////////// // Iterable ////////////////////////////////////////////////////////////////////////// template <> struct front_impl { template static constexpr decltype(auto) apply(Xs&& xs) { return std::get<0>(static_cast(xs)); } }; template <> struct drop_front_impl { template static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence) { return std::make_tuple( hana::at_c(static_cast(xs))... ); } template static constexpr auto apply(Xs&& xs, N const&) { using Raw = typename std::remove_reference::type; constexpr std::size_t n = N::value; constexpr auto len = std::tuple_size::value; return drop_front_helper(static_cast(xs), std::make_index_sequence<(n < len ? len - n : 0)>{}); } }; template <> struct is_empty_impl { template static constexpr auto apply(std::tuple const&) { return hana::bool_c; } }; template <> struct at_impl { template static constexpr decltype(auto) apply(Xs&& xs, N const&) { constexpr std::size_t index = N::value; return std::get(static_cast(xs)); } }; ////////////////////////////////////////////////////////////////////////// // Foldable ////////////////////////////////////////////////////////////////////////// template <> struct length_impl { template static constexpr auto apply(std::tuple const&) { return hana::size_c; } }; ////////////////////////////////////////////////////////////////////////// // Sequence ////////////////////////////////////////////////////////////////////////// template <> struct Sequence { static constexpr bool value = true; }; BOOST_HANA_NAMESPACE_END #endif // !BOOST_HANA_EXT_STD_TUPLE_HPP