46 template <
typename T, u
int8_t N>
class Array;
72 template <
typename T>
struct Ptr;
74 template <
class _ToType,
class _FromType>
75 constexpr _ToType __bit_cast(
const _FromType &__from) {
76 return __builtin_bit_cast(_ToType, __from);
81 static_assert(!std::is_volatile_v<T>,
"volatile types are not supported");
82 static_assert(std::is_trivial_v<T>,
"non-trivial types are unsupported");
83 static_assert(std::is_standard_layout_v<T>,
84 "non-standard layout types are unsupported");
85 static_assert(std::alignment_of_v<T> == 1,
"aligned types are not supported");
98 for (
uint8_t ByteIdx = 0; ByteIdx <
sizeof(T); ++ByteIdx)
99 BytePtrs[ByteIdx] = &ByteArrays[ByteIdx][Idx];
106 for (
uint8_t ByteIdx = 0; ByteIdx <
sizeof(T); ++ByteIdx)
107 BytePtrs[ByteIdx] = &ByteArrays[ByteIdx][Idx];
114 [[clang::always_inline]] T
get()
const {
return static_cast<T
>(*this); }
116 [[clang::always_inline]] constexpr
operator T()
const {
119 for (
uint8_t Idx = 0; Idx <
sizeof(T); ++Idx)
121 return __bit_cast<T>(Bytes);
124 template <
typename... ArgsT>
125 [[clang::always_inline]]
auto operator()(ArgsT &&...Args)
const ->
auto {
126 return static_cast<const T
>(
get())(std::forward<ArgsT>(Args)...);
129 template <
typename Q = T>
130 [[clang::always_inline]] std::enable_if_t<!std::is_const_v<Q>,
const Ptr<T> &>
132 auto *Bytes =
reinterpret_cast<const uint8_t *
>(&Val);
134 for (
uint8_t Idx = 0; Idx <
sizeof(T); ++Idx)
136 return *
static_cast<Ptr<T> *
>(
this);
139 template <
typename Q = T>
140 [[clang::always_inline]] std::enable_if_t<std::is_pointer_v<Q>,
const T>
144 template <
typename Q = T>
145 [[clang::always_inline]] std::enable_if_t<std::is_pointer_v<Q>, T>
155 [[clang::always_inline]] ConstWrapper(
const Ptr<T> &P) : V(P) {}
156 [[clang::always_inline]]
const T *
operator->()
const {
return &V; }
160 template <
typename Q = T>
161 [[clang::always_inline]] std::enable_if_t<!std::is_pointer_v<Q>, ConstWrapper>
163 return *
static_cast<const Ptr<T> *
>(
this);
166 template <
typename U>
168 *
this = *
this + Right;
169 return *
static_cast<Ptr<T> *
>(
this);
172 template <
typename U>
174 *
this = *
this - Right;
175 return *
static_cast<Ptr<T> *
>(
this);
178 template <
typename U>
180 *
this = *
this * Right;
181 return *
static_cast<Ptr<T> *
>(
this);
184 template <
typename U>
186 *
this = *
this / Right;
187 return *
static_cast<Ptr<T> *
>(
this);
190 template <
typename U>
192 *
this = *
this % Right;
193 return *
static_cast<Ptr<T> *
>(
this);
196 template <
typename U>
198 *
this = *
this ^ Right;
199 return *
static_cast<Ptr<T> *
>(
this);
202 template <
typename U>
204 *
this = *
this & Right;
205 return *
static_cast<Ptr<T> *
>(
this);
208 template <
typename U>
210 *
this = *
this | Right;
211 return *
static_cast<Ptr<T> *
>(
this);
214 template <
typename U>
216 *
this = *
this << Right;
217 return *
static_cast<Ptr<T> *
>(
this);
220 template <
typename U>
222 *
this = *
this >> Right;
223 return *
static_cast<Ptr<T> *
>(
this);
228 return *
static_cast<Ptr<T> *
>(
this);
232 return *
static_cast<Ptr<T> *
>(
this);
238 return *
static_cast<Ptr<T> *
>(
this);
244 return *
static_cast<Ptr<T> *
>(
this);
254 template <
typename T, u
int8_t N>
class Ptr<T[N]> {
255 static_assert(!std::is_volatile_v<T>,
"volatile types are not supported");
256 static_assert(std::is_trivial_v<T>,
"non-trivial types are unsupported");
257 static_assert(std::is_standard_layout_v<T>,
258 "non-standard layout types are unsupported");
259 static_assert(std::alignment_of_v<T> == 1,
"aligned types are not supported");
262 [[clang::always_inline]]
Ptr<T> *ptrs() {
263 return reinterpret_cast<Ptr<T> *
>(PtrStorage);
268 [[clang::always_inline]] constexpr
Ptr(
const uint8_t ByteArrays[][M],
271 for (
uint8_t ArrayIdx = 0; ArrayIdx < N; ++ArrayIdx)
272 new (&ptrs()[ArrayIdx])
Ptr<T>(ByteArrays + ArrayIdx *
sizeof(T), Idx);
278 for (
uint8_t ArrayIdx = 0; ArrayIdx < N; ++ArrayIdx)
279 new (&ptrs()[ArrayIdx])
Ptr<T>(ByteArrays + ArrayIdx *
sizeof(T), Idx);
287 friend class Array<T, N>;
305 return &
A == &Other.
A &&
Idx == Other.
Idx;
308 return !(*
this == Other);
312 template <
typename T, u
int8_t N>
314 friend class Array<T, N>;
333 template <
typename T, u
int8_t N>
class Array {
334 static_assert(!std::is_volatile_v<T>,
"volatile types are not supported");
335 static_assert(std::is_trivial_v<T>,
"non-trivial types are unsupported");
336 static_assert(std::is_standard_layout_v<T>,
337 "only standard layout types are supported");
338 static_assert(std::alignment_of_v<T> == 1,
"aligned types are not supported");
340 uint8_t ByteArrays[
sizeof(T)][N];
347 for (
const T &Entry : Entries) {
351 for (
uint8_t ByteIdx = 0; ByteIdx <
sizeof(T); ++ByteIdx)
352 ByteArrays[ByteIdx][Idx] = Bytes[ByteIdx];
359 [[clang::always_inline]] constexpr
Array() =
default;
363 memcpy(ByteArrays, Other.ByteArrays,
sizeof(Other.ByteArrays));
367 return {ByteArrays, Idx};
371 return {ByteArrays, Idx};
378 return {*
this,
size()};
385 return {*
this,
size()};
388 [[clang::always_inline]] constexpr
uint8_t size()
const {
return N; }
uint8_t Idx
Definition: soa.h:291
const Array< T, N > & A
Definition: soa.h:290
bool operator==(const ArrayConstIterator &Other) const
Definition: soa.h:304
bool operator!=(const ArrayConstIterator &Other) const
Definition: soa.h:307
ArrayConstIterator(const Array< T, N > &A, uint8_t Idx)
Definition: soa.h:293
ArrayConstIterator & operator++()
Definition: soa.h:299
Ptr< const T > operator*() const
Definition: soa.h:297
ArrayIterator & operator++()
Definition: soa.h:327
Ptr< T > operator*() const
Definition: soa.h:323
constexpr Array()=default
constexpr ArrayConstIterator< T, N > end() const
Definition: soa.h:377
constexpr ArrayIterator< T, N > end()
Definition: soa.h:384
constexpr ArrayConstIterator< T, N > begin() const
Definition: soa.h:374
constexpr Ptr< T > operator[](uint8_t Idx)
Definition: soa.h:366
constexpr ArrayIterator< T, N > begin()
Definition: soa.h:381
constexpr Ptr< const T > operator[](uint8_t Idx) const
Definition: soa.h:370
constexpr Array(const Array< T, M > &Other)
Definition: soa.h:362
constexpr Array(std::initializer_list< T > Entries)
Definition: soa.h:345
constexpr uint8_t size() const
Definition: soa.h:388
Base class for pointer to array elements.
Definition: soa.h:80
std::enable_if_t< std::is_pointer_v< Q >, T > operator->()
Definition: soa.h:146
Ptr< T > & operator^=(const U &Right)
Definition: soa.h:197
std::enable_if_t<!std::is_const_v< Q >, const Ptr< T > & > operator=(const T &Val)
Definition: soa.h:131
Ptr< T > & operator>>=(const U &Right)
Definition: soa.h:221
Ptr< T > & operator<<=(const U &Right)
Definition: soa.h:215
Ptr< T > & operator%=(const U &Right)
Definition: soa.h:191
Ptr< T > & operator+=(const U &Right)
Definition: soa.h:167
T get() const
Definition: soa.h:114
Ptr< T > & operator|=(const U &Right)
Definition: soa.h:209
Ptr< T > & operator-=(const U &Right)
Definition: soa.h:173
const uint8_t * BytePtrs[sizeof(T)]
Definition: soa.h:81
Ptr< T > & operator++()
Definition: soa.h:226
Ptr< T > & operator--()
Definition: soa.h:230
Ptr< T > & operator&=(const U &Right)
Definition: soa.h:203
auto operator()(ArgsT &&...Args) const -> auto
Definition: soa.h:125
Ptr< T > & operator*=(const U &Right)
Definition: soa.h:179
T operator--(int)
Definition: soa.h:241
constexpr BasePtr(const uint8_t ByteArrays[][N], uint8_t Idx)
Definition: soa.h:95
std::enable_if_t< std::is_pointer_v< Q >, const T > operator->() const
Definition: soa.h:141
std::enable_if_t<!std::is_pointer_v< Q >, ConstWrapper > operator->() const
Definition: soa.h:162
Ptr< T > & operator/=(const U &Right)
Definition: soa.h:185
T operator++(int)
Definition: soa.h:235
constexpr BasePtr(uint8_t ByteArrays[][N], uint8_t Idx)
Definition: soa.h:103
Ptr< const T > operator[](uint8_t Idx) const
Definition: soa.h:282
constexpr Ptr(const uint8_t ByteArrays[][M], uint8_t Idx)
Definition: soa.h:268
constexpr Ptr(uint8_t ByteArrays[][M], uint8_t Idx)
Definition: soa.h:276
Definition: initializer_list:8
::uint8_t uint8_t
Definition: cstdint:21
void * memcpy(void *__restrict__ s1, const void *__restrict__ s2, size_t n)