Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:57

0001 /*!
0002 @file
0003 Adapts `std::array` for use with Hana.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0008  */
0009 
0010 #ifndef BOOST_HANA_EXT_STD_ARRAY_HPP
0011 #define BOOST_HANA_EXT_STD_ARRAY_HPP
0012 
0013 #include <boost/hana/bool.hpp>
0014 #include <boost/hana/config.hpp>
0015 #include <boost/hana/detail/algorithm.hpp>
0016 #include <boost/hana/fwd/at.hpp>
0017 #include <boost/hana/fwd/core/tag_of.hpp>
0018 #include <boost/hana/fwd/drop_front.hpp>
0019 #include <boost/hana/fwd/equal.hpp>
0020 #include <boost/hana/fwd/is_empty.hpp>
0021 #include <boost/hana/fwd/length.hpp>
0022 #include <boost/hana/fwd/less.hpp>
0023 #include <boost/hana/integral_constant.hpp>
0024 
0025 #include <array>
0026 #include <cstddef>
0027 #include <type_traits>
0028 #include <utility>
0029 
0030 
0031 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0032 namespace std {
0033     //! @ingroup group-ext-std
0034     //! Adaptation of `std::array` for Hana.
0035     //!
0036     //!
0037     //!
0038     //! Modeled concepts
0039     //! ----------------
0040     //! 1. `Comparable`\n
0041     //! `std::array`s are compared as per `std::equal`, except that two arrays
0042     //! with different sizes compare unequal instead of triggering an error
0043     //! and the result of the comparison is `constexpr` if both arrays are
0044     //! `constexpr`.
0045     //! @include example/ext/std/array/comparable.cpp
0046     //!
0047     //! 2. `Orderable`\n
0048     //! `std::array`s are ordered with the usual lexicographical ordering,
0049     //! except that two arrays with different size can be ordered instead
0050     //! of triggering an error and the result of the comparison is `constexpr`
0051     //! if both arrays are `constexpr`.
0052     //! @include example/ext/std/array/orderable.cpp
0053     //!
0054     //! 3. `Foldable`\n
0055     //! Folding an array from the left is equivalent to calling
0056     //! `std::accumulate` on it, except it can be `constexpr`.
0057     //! @include example/ext/std/array/foldable.cpp
0058     //!
0059     //! 4. `Iterable`\n
0060     //! Iterating over a `std::array` is equivalent to iterating over it with
0061     //! a normal `for` loop.
0062     //! @include example/ext/std/array/iterable.cpp
0063     template <typename T, std::size_t N>
0064     struct array { };
0065 }
0066 #endif
0067 
0068 
0069 namespace boost { namespace hana {
0070     namespace ext { namespace std { struct array_tag; }}
0071 
0072     template <typename T, std::size_t N>
0073     struct tag_of<std::array<T, N>> {
0074         using type = ext::std::array_tag;
0075     };
0076 
0077     //////////////////////////////////////////////////////////////////////////
0078     // Foldable
0079     //////////////////////////////////////////////////////////////////////////
0080     template <>
0081     struct length_impl<ext::std::array_tag> {
0082         template <typename Xs>
0083         static constexpr auto apply(Xs const&) {
0084             return hana::size_c<std::tuple_size<Xs>::type::value>;
0085         }
0086     };
0087 
0088     //////////////////////////////////////////////////////////////////////////
0089     // Iterable
0090     //////////////////////////////////////////////////////////////////////////
0091     template <>
0092     struct at_impl<ext::std::array_tag> {
0093         template <typename Xs, typename N>
0094         static constexpr decltype(auto) apply(Xs&& xs, N const&) {
0095             constexpr std::size_t n = N::value;
0096             return std::get<n>(static_cast<Xs&&>(xs));
0097         }
0098     };
0099 
0100     template <>
0101     struct drop_front_impl<ext::std::array_tag> {
0102         template <std::size_t n, typename Xs, std::size_t ...i>
0103         static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
0104             using T = typename std::remove_reference<Xs>::type::value_type;
0105             return std::array<T, sizeof...(i)>{{static_cast<Xs&&>(xs)[n + i]...}};
0106         }
0107 
0108         template <typename Xs, typename N>
0109         static constexpr auto apply(Xs&& xs, N const&) {
0110             constexpr std::size_t n = N::value;
0111             constexpr std::size_t len = std::tuple_size<
0112                 typename std::remove_cv<
0113                     typename std::remove_reference<Xs>::type
0114                 >::type
0115             >::value;
0116             return drop_front_helper<n>(static_cast<Xs&&>(xs),
0117                     std::make_index_sequence<(n < len ? len - n : 0)>{});
0118         }
0119     };
0120 
0121     template <>
0122     struct is_empty_impl<ext::std::array_tag> {
0123         template <typename T, std::size_t N>
0124         static constexpr auto apply(std::array<T, N> const&) {
0125             return hana::bool_c<N == 0>;
0126         }
0127     };
0128 
0129     //////////////////////////////////////////////////////////////////////////
0130     // Comparable
0131     //////////////////////////////////////////////////////////////////////////
0132     template <>
0133     struct equal_impl<ext::std::array_tag, ext::std::array_tag> {
0134         template <typename T, std::size_t n, typename U>
0135         static constexpr bool apply(std::array<T, n> const& xs, std::array<U, n> const& ys)
0136         { return detail::equal(&xs[0], &xs[0] + n, &ys[0], &ys[0] + n); }
0137 
0138         template <typename T, typename U>
0139         static constexpr auto apply(std::array<T, 0> const&, std::array<U, 0> const&)
0140         { return hana::true_c; }
0141 
0142         template <typename T, std::size_t n, typename U, std::size_t m>
0143         static constexpr auto apply(std::array<T, n> const&, std::array<U, m> const&)
0144         { return hana::false_c; }
0145     };
0146 
0147     //////////////////////////////////////////////////////////////////////////
0148     // Orderable
0149     //////////////////////////////////////////////////////////////////////////
0150     template <>
0151     struct less_impl<ext::std::array_tag, ext::std::array_tag> {
0152         template <typename T, std::size_t n, typename U, std::size_t m>
0153         static constexpr auto apply(std::array<T, n> const& xs, std::array<U, m> const& ys) {
0154             // This logic is more complex than it needs to be because we can't
0155             // use `.begin()` and `.end()`, which are not constexpr in C++14,
0156             // and because `&arr[0]` is UB when the array is empty.
0157             if (xs.empty()) {
0158                 return !ys.empty();
0159             } else {
0160                 if (ys.empty()) {
0161                     return false;
0162                 } else {
0163                     return detail::lexicographical_compare(&xs[0], &xs[0] + n,
0164                                                            &ys[0], &ys[0] + m);
0165                 }
0166             }
0167         }
0168     };
0169 }} // end namespace boost::hana
0170 
0171 #endif // !BOOST_HANA_EXT_STD_ARRAY_HPP