/*! @file Adapts `std::array` for use with Hana. @copyright Louis Dionne 2013-2017 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_ARRAY_HPP #define BOOST_HANA_EXT_STD_ARRAY_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef BOOST_HANA_DOXYGEN_INVOKED namespace std { //! @ingroup group-ext-std //! Adaptation of `std::array` for Hana. //! //! //! //! Modeled concepts //! ---------------- //! 1. `Comparable`\n //! `std::array`s are compared as per `std::equal`, except that two arrays //! with different sizes compare unequal instead of triggering an error //! and the result of the comparison is `constexpr` if both arrays are //! `constexpr`. //! @include example/ext/std/array/comparable.cpp //! //! 2. `Orderable`\n //! `std::array`s are ordered with the usual lexicographical ordering, //! except that two arrays with different size can be ordered instead //! of triggering an error and the result of the comparison is `constexpr` //! if both arrays are `constexpr`. //! @include example/ext/std/array/orderable.cpp //! //! 3. `Foldable`\n //! Folding an array from the left is equivalent to calling //! `std::accumulate` on it, except it can be `constexpr`. //! @include example/ext/std/array/foldable.cpp //! //! 4. `Iterable`\n //! Iterating over a `std::array` is equivalent to iterating over it with //! a normal `for` loop. //! @include example/ext/std/array/iterable.cpp template struct array { }; } #endif BOOST_HANA_NAMESPACE_BEGIN namespace ext { namespace std { struct array_tag; }} template struct tag_of> { using type = ext::std::array_tag; }; ////////////////////////////////////////////////////////////////////////// // Foldable ////////////////////////////////////////////////////////////////////////// template <> struct length_impl { template static constexpr auto apply(Xs const&) { return hana::size_c::type::value>; } }; ////////////////////////////////////////////////////////////////////////// // Iterable ////////////////////////////////////////////////////////////////////////// template <> struct at_impl { template static constexpr decltype(auto) apply(Xs&& xs, N const&) { constexpr std::size_t n = N::value; return std::get(static_cast(xs)); } }; template <> struct drop_front_impl { template static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence) { using T = typename std::remove_reference::type::value_type; return std::array{{static_cast(xs)[n + i]...}}; } template static constexpr auto apply(Xs&& xs, N const&) { constexpr std::size_t n = N::value; constexpr std::size_t len = std::tuple_size< typename std::remove_cv< typename std::remove_reference::type >::type >::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::array const&) { return hana::bool_c; } }; ////////////////////////////////////////////////////////////////////////// // Comparable ////////////////////////////////////////////////////////////////////////// template <> struct equal_impl { template static constexpr bool apply(std::array const& xs, std::array const& ys) { return detail::equal(&xs[0], &xs[0] + n, &ys[0], &ys[0] + n); } template static constexpr auto apply(std::array const&, std::array const&) { return hana::true_c; } template static constexpr auto apply(std::array const&, std::array const&) { return hana::false_c; } }; ////////////////////////////////////////////////////////////////////////// // Orderable ////////////////////////////////////////////////////////////////////////// template <> struct less_impl { template static constexpr auto apply(std::array const& xs, std::array const& ys) { // This logic is more complex than it needs to be because we can't // use `.begin()` and `.end()`, which are not constexpr in C++14, // and because `&arr[0]` is UB when the array is empty. if (xs.empty()) { return !ys.empty(); } else { if (ys.empty()) { return false; } else { return detail::lexicographical_compare(&xs[0], &xs[0] + n, &ys[0], &ys[0] + m); } } } }; BOOST_HANA_NAMESPACE_END #endif // !BOOST_HANA_EXT_STD_ARRAY_HPP