Array.hpp
1 // 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.hpp"
15 
16 namespace cpp17 {
17 namespace detail {
18 template <typename T, size_t Size, size_t... Is>
19 std::array<T, Size> convert_to_array(const T (&t)[Size],
20  std::index_sequence<Is...> /*meta*/) {
21  return {{t[Is]...}};
22 }
23 } // namespace detail
24 
25 template <typename T, size_t Size>
26 struct array {
27  using value_type = T;
28  using reference = value_type&;
29  using const_reference = const value_type&;
30  using iterator = value_type*;
31  using const_iterator = const value_type*;
32  using pointer = value_type*;
33  using const_pointer = const value_type*;
34  using size_type = size_t;
36 
37  // clang-tidy: mark explicit. We want implicit conversion
38  operator std::array<T, Size>() const noexcept { // NOLINT
39  return detail::convert_to_array(data_, std::make_index_sequence<Size>{});
40  }
41 
42  constexpr iterator begin() noexcept {
43  return iterator(data_); // NOLINT
44 }
45  constexpr const_iterator begin() const noexcept {
46  return const_iterator(data_); // NOLINT
47  }
48  constexpr iterator end() noexcept {
49  return iterator(data_ + Size); // NOLINT
50 }
51  constexpr const_iterator end() const noexcept {
52  return const_iterator(data_ + Size); // NOLINT
53  }
54 
55  constexpr const_iterator cbegin() const noexcept { return begin(); }
56  constexpr const_iterator cend() const noexcept { return end(); }
57 
58  constexpr size_type size() const noexcept { return Size; }
59  constexpr size_type max_size() const noexcept { return Size; }
60  constexpr bool empty() const noexcept { return Size == 0; }
61 
62  constexpr reference operator[](const size_type i) noexcept {
63  return data_[i]; // NOLINT
64  }
65  constexpr const_reference operator[](const size_type i) const noexcept {
66  return data_[i]; // NOLINT
67  }
68 
69  constexpr reference at(const size_type i) noexcept {
70  return data_[i]; // NOLINT
71  }
72  constexpr const_reference at(const size_type i) const noexcept {
73  return data_[i]; // NOLINT
74  }
75 
76  constexpr reference front() { return data_[0]; }
77  constexpr const_reference front() const { return data_[0]; }
78  constexpr reference back() { return data_[Size > 0 ? Size - 1 : 0]; }
79  constexpr const_reference back() const {
80  return data_[Size > 0 ? Size - 1 : 0];
81  }
82 
83  constexpr value_type* data() noexcept { return data_; }
84  constexpr const value_type* data() const noexcept { return data_; }
85 
86  value_type data_[Size > 0 ? Size : 1];
87 };
88 namespace detail {
89 template <typename T = void>
90 struct Equal : std::binary_function<T, T, bool> {
91  constexpr bool inline operator()(const T& lhs, const T& rhs) const {
92  return lhs == rhs;
93  }
94 };
95 
96 template <>
97 struct Equal<void> {
98  template <class T0, class T1>
99  constexpr bool inline operator()(T0&& lhs, T1&& rhs) const
100  noexcept(noexcept(std::forward<T0>(lhs) == std::forward<T1>(rhs))) {
101  return std::forward<T0>(lhs) == std::forward<T1>(rhs);
102  }
103 };
104 } // namespace detail
105 
106 template <typename InputIter1, typename InputIter2,
107  typename BinaryPred = detail::Equal<>>
108 constexpr bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
109  BinaryPred pred = detail::Equal<>{}) {
110  for (; first1 != last1; ++first1, ++first2) {
111  if (not pred(*first1, *first2)) {
112  return false;
113  }
114  }
115  return true;
116 }
117 
118 template <typename InputIter1, typename InputIter2,
119  typename BinaryPred = std::less_equal<>>
120 constexpr bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
121  InputIter2 first2, InputIter2 last2,
122  BinaryPred pred = std::less_equal<>{}) {
123  for (; first2 != last2; ++first1, ++first2) {
124  if (first1 == last1 or pred(*first1, *first2)) {
125  return true;
126  } else if (pred(*first2, *first1)) {
127  return false;
128  }
129  }
130  return false;
131 }
132 
133 template <class T, size_t Size>
134 inline constexpr bool operator==(const array<T, Size>& x,
135  const array<T, Size>& y) {
136  return equal(x.data_, x.data_ + Size, y.data_); // NOLINT
137 }
138 
139 template <class T, size_t Size>
140 inline constexpr bool operator!=(const array<T, Size>& lhs,
141  const array<T, Size>& rhs) {
142  return not(lhs == rhs);
143 }
144 
145 template <class T, size_t Size>
146 inline constexpr bool operator<(const array<T, Size>& lhs,
147  const array<T, Size>& rhs) {
148  return lexicographical_compare(lhs.__elems_, lhs.__elems_ + Size,
149  rhs.__elems_, rhs.__elems_ + Size);
150 }
151 
152 template <class T, size_t Size>
153 inline constexpr bool operator>(const array<T, Size>& lhs,
154  const array<T, Size>& rhs) {
155  return rhs < lhs;
156 }
157 
158 template <class T, size_t Size>
159 inline constexpr bool operator<=(const array<T, Size>& lhs,
160  const array<T, Size>& rhs) {
161  return not(rhs < lhs);
162 }
163 
164 template <class T, size_t Size>
165 inline constexpr bool operator>=(const array<T, Size>& lhs,
166  const array<T, Size>& rhs) {
167  return not(lhs < rhs);
168 }
169 
170 template <typename T>
171 inline std::ostream& operator<<(std::ostream& os, const array<T, 0>& /*a*/) {
172  return os << "()";
173 }
174 
175 template <typename T, size_t N>
176 inline std::ostream& operator<<(std::ostream& os, const array<T, N>& a) {
177  os << '(';
178  for (size_t i = 0; i < N - 1; ++i) {
179  os << a[i] << ',';
180  }
181  if (N > 0) {
182  os << a[N - 1];
183  }
184  os << ')';
185  return os;
186 }
187 } // namespace cpp17
188 
189 namespace detail {
190 template <typename List, size_t... indices,
192 inline constexpr auto make_cpp17_array_from_list_helper(
195  tmpl::size<List>::value> {
197  tmpl::size<List>::value>{
198  {tmpl::at<List, tmpl::size_t<indices>>::value...}};
199 }
200 } // namespace detail
201 
202 /// \ingroup ConstantExpressionsGroup
203 /// Make an array from a typelist that holds std::integral_constant's all of
204 /// which have the same `value_type`
205 ///
206 /// \tparam List the typelist of std::integral_constant's
207 /// \return array of integral values from the typelist
208 template <typename List,
210 inline constexpr auto make_cpp17_array_from_list()
212  tmpl::size<List>::value> {
213  return detail::make_cpp17_array_from_list_helper<List>(
215 }
216 
217 template <typename TypeForZero,
219 inline constexpr cpp17::array<std::decay_t<TypeForZero>, 0>
222 }
223 
224 namespace detail {
225 template <typename T, size_t Size, size_t... Is>
226 inline constexpr cpp17::array<T, Size> convert_to_cpp17_array_impl(
227  const std::array<T, Size>& t,
229  Is...> /*meta*/) noexcept(noexcept(cpp17::array<T, Size>{{t[Is]...}})) {
230  return {{t[Is]...}};
231 }
232 } // namespace detail
233 
234 template <typename T, size_t Size, size_t... Is>
235 inline constexpr cpp17::array<T, Size>
236 convert_to_cpp17_array(const std::array<T, Size>& t) noexcept(noexcept(
237  detail::convert_to_cpp17_array_impl(t, std::make_index_sequence<Size>{}))) {
238  return detail::convert_to_cpp17_array_impl(t,
240 }
constexpr auto make_cpp17_array_from_list() -> cpp17::array< std::decay_t< decltype(tmpl::front< List >::value)>, tmpl::size< List >::value >
Make an array from a typelist that holds std::integral_constant&#39;s all of which have the same value_ty...
Definition: Array.hpp:210
Defines the type alias Requires.
Definition: Determinant.hpp:11
Wraps the template metaprogramming library used (brigand)
Definition: Array.hpp:26
typename Requires_detail::requires_impl< B >::template_error_type_failed_to_meet_requirements_on_template_parameters Requires
Express requirements on the template parameters of a function or class, replaces std::enable_if_t ...
Definition: Requires.hpp:67
C++ STL code present in C++17.
Definition: Array.hpp:16
Defines type traits, some of which are future STL type_traits header.
constexpr T & at(std::array< T, N > &arr, Size index)
Retrieve a entry from a container, with checks in Debug mode that the index being retrieved is valid...
Definition: Gsl.hpp:124