Skip to content

Instantly share code, notes, and snippets.

@willwray
Created August 18, 2020 13:35
Show Gist options
  • Save willwray/fb7e6c5d4316a84be361a1d34238e96e to your computer and use it in GitHub Desktop.
Save willwray/fb7e6c5d4316a84be361a1d34238e96e to your computer and use it in GitHub Desktop.
simple c++20 array
// https://godbolt.org/z/cdjrj4
#include <compare>
#include <concepts>
// same_ish<T> utility concept to match a forwarding reference argument <T>(T&& a)
template <typename T, typename U> concept same_ish = std::same_as<std::remove_cvref_t<T>,U>;
template <typename A> concept zero_size_array = sizeof(A) == 0 && ! std::is_class_v<A>;
// carray concept designed to match zero-size arrays as well as bounded C-arrays
// (zero-size arrays are a non-standard extension in gcc and clang, so fail -pedantic)
template <typename A> concept carray = zero_size_array<A> || std::is_bounded_array_v<A>;
template <carray A>
struct array
{
A data;
using element_type = std::remove_cvref_t<decltype(*data)>;
static constexpr auto extent_v = sizeof data / sizeof *data;
friend constexpr auto&& data(same_ish<array> auto&& a) noexcept {
return ((decltype(a)&&)a).data;
}
constexpr auto size() const noexcept { return extent_v; }
//friend consteval std::integral_constant<std::size_t,extent_v> size(array const&) noexcept { return {}; }
friend consteval std::size_t size(array const&) noexcept { return extent_v; }
constexpr auto& operator[](int i)& noexcept { return data[i]; }
constexpr auto&& operator[](int i)&& noexcept { return ((A&&)data)[i]; }
constexpr auto& operator[](int i) const& noexcept { return data[i]; }
constexpr auto&& operator[](int i) const&& noexcept { return ((A const&&)data)[i]; }
constexpr auto begin() noexcept { return data; }
constexpr auto end() noexcept { return &data[size()]; }
constexpr auto begin() const noexcept { return data; }
constexpr auto end() const noexcept { return &data[size()]; }
friend constexpr void swap(array& l, array& r) noexcept(std::is_nothrow_swappable_v<A>) {
std::swap(l.data,r.data);
}
friend auto operator<=>(array const&, array const&) noexcept = default;
};
template <carray A> array(A const&) -> array<A>;
template <typename T, int N> array(T const(&)[N]) -> array<T[N]>;
template <typename T, int M, int N> array(T const(&)[M][N]) -> array<T[M][N]>;
// to_array() copy-converts a c-array to array class (redundant with P1997)
constexpr auto to_array(carray auto&& a) -> decltype(array{a});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment