SpECTRE Documentation Coverage Report
Current view: top level - Utilities - Array.hpp Hit Total Coverage
Commit: 52f20d7d69c179a8fabd675cc9d8c5355c7d621c Lines: 2 44 4.5 %
Date: 2024-04-17 15:32:38
Legend: Lines: hit not hit

          Line data    Source code
       1           0 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : #pragma once
       5             : 
       6             : #include <array>
       7             : #include <cstddef>
       8             : #include <functional>
       9             : #include <ostream>
      10             : #include <utility>
      11             : 
      12             : #include "Utilities/Requires.hpp"
      13             : #include "Utilities/TMPL.hpp"
      14             : #include "Utilities/TypeTraits/IsA.hpp"
      15             : 
      16             : namespace cpp20 {
      17             : namespace detail {
      18             : template <typename T, size_t Size, size_t... Is>
      19             : constexpr std::array<T, Size> convert_to_array(
      20             :     // NOLINTNEXTLINE(modernize-avoid-c-arrays)
      21             :     const T (&t)[Size], std::index_sequence<Is...> /*meta*/) {
      22             :   return {{t[Is]...}};
      23             : }
      24             : }  // namespace detail
      25             : 
      26             : /// \brief A `std::array` implementation with partial C++20 support
      27             : ///
      28             : /// \warning This is not a standard-compliant C++20 `std::array` implementation.
      29             : /// We provide this implementation because we need the `constexpr operator==`
      30             : /// from C++20. Note that other C++20 changes, such as the replacement of the
      31             : /// other comparison operators in favor of `operator<=>`, are not implemented.
      32             : /// This class can be removed when we support C++20.
      33             : template <typename T, size_t Size>
      34           1 : struct array {
      35           0 :   using value_type = T;
      36           0 :   using reference = value_type&;
      37           0 :   using const_reference = const value_type&;
      38           0 :   using iterator = value_type*;
      39           0 :   using const_iterator = const value_type*;
      40           0 :   using pointer = value_type*;
      41           0 :   using const_pointer = const value_type*;
      42           0 :   using size_type = size_t;
      43           0 :   using difference_type = std::ptrdiff_t;
      44             : 
      45             :   // clang-tidy: mark explicit. We want implicit conversion
      46             :   constexpr operator std::array<T, Size>() const {  // NOLINT
      47             :     return detail::convert_to_array(data_, std::make_index_sequence<Size>{});
      48             :   }
      49             : 
      50           0 :   constexpr iterator begin() {
      51             :     return iterator(data_);  // NOLINT
      52             :   }
      53           0 :   constexpr const_iterator begin() const {
      54             :     return const_iterator(data_);  // NOLINT
      55             :   }
      56           0 :   constexpr iterator end() {
      57             :     return iterator(data_ + Size);  // NOLINT
      58             :   }
      59           0 :   constexpr const_iterator end() const {
      60             :     return const_iterator(data_ + Size);  // NOLINT
      61             :   }
      62             : 
      63           0 :   constexpr const_iterator cbegin() const { return begin(); }
      64           0 :   constexpr const_iterator cend() const { return end(); }
      65             : 
      66           0 :   constexpr size_type size() const { return Size; }
      67           0 :   constexpr size_type max_size() const { return Size; }
      68           0 :   constexpr bool empty() const { return Size == 0; }
      69             : 
      70           0 :   constexpr reference operator[](const size_type i) {
      71             :     return data_[i];  // NOLINT
      72             :   }
      73           0 :   constexpr const_reference operator[](const size_type i) const {
      74             :     return data_[i];  // NOLINT
      75             :   }
      76             : 
      77           0 :   constexpr reference at(const size_type i) {
      78             :     return data_[i];  // NOLINT
      79             :   }
      80           0 :   constexpr const_reference at(const size_type i) const {
      81             :     return data_[i];  // NOLINT
      82             :   }
      83             : 
      84           0 :   constexpr reference front() { return data_[0]; }
      85           0 :   constexpr const_reference front() const { return data_[0]; }
      86           0 :   constexpr reference back() { return data_[Size > 0 ? Size - 1 : 0]; }
      87           0 :   constexpr const_reference back() const {
      88             :     return data_[Size > 0 ? Size - 1 : 0];
      89             :   }
      90             : 
      91           0 :   constexpr value_type* data() { return data_; }
      92           0 :   constexpr const value_type* data() const { return data_; }
      93             : 
      94             :   // NOLINTNEXTLINE(modernize-avoid-c-arrays)
      95           0 :   value_type data_[Size > 0 ? Size : 1];
      96             : };
      97             : namespace detail {
      98             : template <typename T = void>
      99             : struct Equal {
     100             :   constexpr bool inline operator()(const T& lhs, const T& rhs) const {
     101             :     return lhs == rhs;
     102             :   }
     103             : };
     104             : 
     105             : template <>
     106             : struct Equal<void> {
     107             :   template <class T0, class T1>
     108             :   constexpr bool inline operator()(T0&& lhs, T1&& rhs) const {
     109             :     return std::forward<T0>(lhs) == std::forward<T1>(rhs);
     110             :   }
     111             : };
     112             : }  // namespace detail
     113             : 
     114             : template <typename InputIter1, typename InputIter2,
     115             :           typename BinaryPred = detail::Equal<>>
     116           0 : constexpr bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
     117             :                      BinaryPred pred = detail::Equal<>{}) {
     118             :   for (; first1 != last1; ++first1, ++first2) {
     119             :     if (not pred(*first1, *first2)) {
     120             :       return false;
     121             :     }
     122             :   }
     123             :   return true;
     124             : }
     125             : 
     126             : template <typename InputIter1, typename InputIter2,
     127             :           typename BinaryPred = std::less_equal<>>
     128           0 : constexpr bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
     129             :                                        InputIter2 first2, InputIter2 last2,
     130             :                                        BinaryPred pred = std::less_equal<>{}) {
     131             :   for (; first2 != last2; ++first1, ++first2) {
     132             :     if (first1 == last1 or pred(*first1, *first2)) {
     133             :       return true;
     134             :     } else if (pred(*first2, *first1)) {
     135             :       return false;
     136             :     }
     137             :   }
     138             :   return false;
     139             : }
     140             : 
     141             : template <class T, size_t Size>
     142           0 : inline constexpr bool operator==(const array<T, Size>& x,
     143             :                                  const array<T, Size>& y) {
     144             :   return equal(x.data_, x.data_ + Size, y.data_);  // NOLINT
     145             : }
     146             : 
     147             : template <class T, size_t Size>
     148           0 : inline constexpr bool operator!=(const array<T, Size>& lhs,
     149             :                                  const array<T, Size>& rhs) {
     150             :   return not(lhs == rhs);
     151             : }
     152             : 
     153             : template <class T, size_t Size>
     154           0 : inline constexpr bool operator<(const array<T, Size>& lhs,
     155             :                                 const array<T, Size>& rhs) {
     156             :   return lexicographical_compare(lhs.__elems_, lhs.__elems_ + Size,
     157             :                                  rhs.__elems_, rhs.__elems_ + Size);
     158             : }
     159             : 
     160             : template <class T, size_t Size>
     161           0 : inline constexpr bool operator>(const array<T, Size>& lhs,
     162             :                                 const array<T, Size>& rhs) {
     163             :   return rhs < lhs;
     164             : }
     165             : 
     166             : template <class T, size_t Size>
     167           0 : inline constexpr bool operator<=(const array<T, Size>& lhs,
     168             :                                  const array<T, Size>& rhs) {
     169             :   return not(rhs < lhs);
     170             : }
     171             : 
     172             : template <class T, size_t Size>
     173           0 : inline constexpr bool operator>=(const array<T, Size>& lhs,
     174             :                                  const array<T, Size>& rhs) {
     175             :   return not(lhs < rhs);
     176             : }
     177             : 
     178             : template <typename T>
     179           0 : inline std::ostream& operator<<(std::ostream& os, const array<T, 0>& /*a*/) {
     180             :   return os << "()";
     181             : }
     182             : 
     183             : template <typename T, size_t N>
     184           0 : inline std::ostream& operator<<(std::ostream& os, const array<T, N>& a) {
     185             :   os << '(';
     186             :   for (size_t i = 0; i < N - 1; ++i) {
     187             :     os << a[i] << ',';
     188             :   }
     189             :   if (N > 0) {
     190             :     os << a[N - 1];
     191             :   }
     192             :   os << ')';
     193             :   return os;
     194             : }
     195             : }  // namespace cpp20
     196             : 
     197             : namespace detail {
     198             : template <typename List, size_t... indices,
     199             :           Requires<not tt::is_a_v<tmpl::list, tmpl::front<List>>> = nullptr>
     200             : inline constexpr auto make_cpp20_array_from_list_helper(
     201             :     std::integer_sequence<size_t, indices...> /*meta*/)
     202             :     -> cpp20::array<std::decay_t<decltype(tmpl::front<List>::value)>,
     203             :                     tmpl::size<List>::value> {
     204             :   return cpp20::array<std::decay_t<decltype(tmpl::front<List>::value)>,
     205             :                       tmpl::size<List>::value>{
     206             :       {tmpl::at<List, tmpl::size_t<indices>>::value...}};
     207             : }
     208             : }  // namespace detail
     209             : 
     210             : /// \ingroup ConstantExpressionsGroup
     211             : /// Make an array from a typelist that holds std::integral_constant's all of
     212             : /// which have the same `value_type`
     213             : ///
     214             : /// \tparam List the typelist of std::integral_constant's
     215             : /// \return array of integral values from the typelist
     216             : template <typename List,
     217             :           Requires<not tt::is_a_v<tmpl::list, tmpl::front<List>>> = nullptr>
     218           1 : inline constexpr auto make_cpp20_array_from_list()
     219             :     -> cpp20::array<std::decay_t<decltype(tmpl::front<List>::value)>,
     220             :                     tmpl::size<List>::value> {
     221             :   return detail::make_cpp20_array_from_list_helper<List>(
     222             :       std::make_integer_sequence<size_t, tmpl::size<List>::value>{});
     223             : }
     224             : 
     225             : template <typename TypeForZero,
     226             :           Requires<not tt::is_a_v<tmpl::list, TypeForZero>> = nullptr>
     227             : inline constexpr cpp20::array<std::decay_t<TypeForZero>, 0>
     228           0 : make_cpp20_array_from_list() {
     229             :   return cpp20::array<std::decay_t<TypeForZero>, 0>{{}};
     230             : }
     231             : 
     232             : namespace detail {
     233             : template <typename T, size_t Size, size_t... Is>
     234             : inline constexpr cpp20::array<T, Size> convert_to_cpp20_array_impl(
     235             :     const std::array<T, Size>& t,
     236             :     std::index_sequence<
     237             :         Is...> /*meta*/) {
     238             :   return {{t[Is]...}};
     239             : }
     240             : }  // namespace detail
     241             : 
     242             : template <typename T, size_t Size, size_t... Is>
     243             : inline constexpr cpp20::array<T, Size>
     244           0 : convert_to_cpp20_array(const std::array<T, Size>& t) {
     245             :   return detail::convert_to_cpp20_array_impl(t,
     246             :                                              std::make_index_sequence<Size>{});
     247             : }

Generated by: LCOV version 1.14