Skip to content

Commit b02da54

Browse files
Add iterators
1 parent d59cc94 commit b02da54

2 files changed

Lines changed: 134 additions & 71 deletions

File tree

memlayout/wrapper.h

Lines changed: 128 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
#ifndef WRAPPER_H
2-
#define WRAPPER_H
1+
#ifndef MEMLAYOUT_H
2+
#define MEMLAYOUT_H
3+
4+
namespace std { template<class T> struct iterator_traits; }
35

46
namespace memlayout {
57

@@ -12,6 +14,14 @@ template <class T> using const_reference = const T&;
1214
template <class T> using pointer = T*;
1315
template <class T> using const_pointer = const T*;
1416

17+
struct Dummy {};
18+
19+
template<template <class> class Container>
20+
concept random_access_like = requires(Container<Dummy> it, size_t n) { it + n; it - n; it - it; it[n]; ++it; --it; *it; };
21+
22+
template<template <class> class Iterator>
23+
concept non_const_iterator_like = requires(Iterator<Dummy> it) { *it = Dummy{}; };
24+
1525
template <class ReturnType>
1626
struct RandomAccessAt {
1727
memlayout::size_t i;
@@ -68,6 +78,22 @@ struct CopyAssignment {
6878
constexpr Left& operator()(Left& left, const Right& right) const { return left = right; }
6979
};
7080

81+
template <class ReturnType>
82+
struct Begin {
83+
template <class... Args>
84+
constexpr ReturnType operator()(Args& ...args) const { return {args.begin()...}; }
85+
template <class... Args>
86+
constexpr ReturnType operator()(const Args& ...args) const { return {args.cbegin()...}; }
87+
};
88+
89+
template <class ReturnType>
90+
struct End {
91+
template <class... Args>
92+
constexpr ReturnType operator()(Args& ...args) const { return {args.end()...}; }
93+
template <class... Args>
94+
constexpr ReturnType operator()(const Args& ...args) const { return {args.cend()...}; }
95+
};
96+
7197
enum class Layout { aos = 0, soa = 1 };
7298

7399
template <
@@ -115,16 +141,19 @@ struct Wrapper<Struct, pointer, Layout::aos> {
115141
constexpr Wrapper operator-(ptrdiff_t i) const { return {data - i}; }
116142
constexpr ptrdiff_t operator-(const Wrapper& other) const { return {data - other.data}; }
117143

118-
constexpr Wrapper& operator++() { return {++data}; }
119-
constexpr Wrapper& operator+=(ptrdiff_t i) { return {data += i}; }
120-
constexpr Wrapper& operator--() { return {--data}; }
121-
constexpr Wrapper& operator-=(ptrdiff_t i) { return {data -= i}; }
144+
constexpr Wrapper operator++() { return {++data}; }
145+
constexpr Wrapper operator+=(ptrdiff_t i) { return {data += i}; }
146+
constexpr Wrapper operator--() { return {--data}; }
147+
constexpr Wrapper operator-=(ptrdiff_t i) { return {data -= i}; }
122148

123149
constexpr Wrapper<Struct, reference> operator[] (size_t i) { return data[i]; }
124150
constexpr Wrapper<Struct, const_reference> operator[] (size_t i) const { return data[i]; }
125151

126152
constexpr Wrapper<Struct, reference> operator*() { return *data; }
127153
constexpr Wrapper<Struct, const_reference> operator*(ptrdiff_t) const { return *data; }
154+
155+
constexpr Wrapper<Struct, reference> operator->() { return operator[](0); }
156+
constexpr Wrapper<Struct, const_reference> operator->() const { return operator[](0); }
128157
};
129158

130159
template <
@@ -135,6 +164,10 @@ struct Wrapper<Struct, Container, Layout::soa> : public Struct<Container> {
135164
static constexpr Layout layout_type = Layout::soa;
136165
using Base = Struct<Container>;
137166
using Base::Base;
167+
template <class T>
168+
using iterator = typename Container<T>::iterator;
169+
template <class T>
170+
using const_iterator = typename Container<T>::const_iterator;
138171

139172
constexpr Wrapper() = default;
140173
constexpr Wrapper(Base b) : Base{static_cast<Base&&>(b)} {}
@@ -148,6 +181,91 @@ struct Wrapper<Struct, Container, Layout::soa> : public Struct<Container> {
148181

149182
constexpr Wrapper<Struct, reference> operator*() { return operator[](0); }
150183
constexpr Wrapper<Struct, const_reference> operator*(ptrdiff_t) const { return operator[](0); }
184+
185+
constexpr Wrapper<Struct, iterator> begin() { return Base::apply(Begin<Struct<iterator>>{}); }
186+
constexpr Wrapper<Struct, iterator> end() { return Base::apply(End<Struct<iterator>>{}); }
187+
constexpr Wrapper<Struct, const_iterator> cbegin() const { return Base::apply(Begin<Struct<const_iterator>>{}); }
188+
constexpr Wrapper<Struct, const_iterator> cend() const { return Base::apply(End<Struct<const_iterator>>{}); }
189+
};
190+
191+
template <
192+
template <template <class> class> class Struct,
193+
template <class> class Container
194+
>
195+
requires random_access_like<Container>
196+
struct Wrapper<Struct, Container, Layout::soa> : public Struct<Container> {
197+
using iterator_category = std::iterator_traits<Container<Dummy>>::iterator_category;
198+
using difference_type = ptrdiff_t;
199+
using value_type = Wrapper<Struct, memlayout::value>;
200+
using pointer = void;
201+
using reference = Wrapper<Struct, memlayout::reference>;
202+
203+
static constexpr Layout layout_type = Layout::soa;
204+
using Base = Struct<Container>;
205+
206+
constexpr Wrapper() = default;
207+
constexpr Wrapper(Base b) : Base{static_cast<Base&&>(b)} {}
208+
209+
constexpr Wrapper<Struct, memlayout::reference> operator[] (size_t i) { return Base::apply(RandomAccessAt<Struct<memlayout::reference>>{i}); }
210+
constexpr const Wrapper<Struct, memlayout::const_reference> operator[] (size_t i) const { return Base::apply(RandomAccessAt<Struct<memlayout::const_reference>>{i}); }
211+
212+
constexpr Wrapper<Struct, memlayout::reference> operator*() { return operator[](0); }
213+
constexpr Wrapper<Struct, memlayout::const_reference> operator*() const { return operator[](0); }
214+
constexpr Wrapper<Struct, memlayout::reference> operator->() { return operator[](0); }
215+
constexpr Wrapper<Struct, memlayout::const_reference> operator->() const { return operator[](0); }
216+
217+
constexpr bool operator==(const Wrapper& other) const { return Base::apply(FirstMember{}) == other.apply(FirstMember{}); }
218+
constexpr bool operator!=(const Wrapper& other) const { return !this->operator==(other); }
219+
constexpr bool operator<(const Wrapper& other) const { return Base::apply(FirstMember{}) < other.apply(FirstMember{}); }
220+
221+
constexpr Wrapper operator+(ptrdiff_t i) const { return Base::apply(Advance<Base>{i}); }
222+
constexpr Wrapper operator-(ptrdiff_t i) const { return operator+(-i); }
223+
constexpr ptrdiff_t operator-(const Wrapper& other) const { return Base::apply(FirstMember{}) - other.apply(FirstMember{}); }
224+
225+
constexpr Wrapper& operator++() { Base::apply(PreIncrement<Base>{}); return *this; }
226+
constexpr Wrapper& operator+=(ptrdiff_t i) { return *this = *this + i; }
227+
constexpr Wrapper& operator--() { Base::apply(PreDecrement<Base>{}); return *this; }
228+
constexpr Wrapper& operator-=(ptrdiff_t i) { return *this = *this - i; }
229+
};
230+
231+
template <
232+
template <template <class> class> class Struct,
233+
template <class> class Container
234+
>
235+
requires (random_access_like<Container> && !non_const_iterator_like<Container>)
236+
struct Wrapper<Struct, Container, Layout::soa> : public Struct<Container> {
237+
using iterator_category = std::iterator_traits<Container<Dummy>>::iterator_category;
238+
using difference_type = ptrdiff_t;
239+
using value_type = Wrapper<Struct, memlayout::value>;
240+
using pointer = void;
241+
using reference = Wrapper<Struct, memlayout::const_reference>;
242+
243+
static constexpr Layout layout_type = Layout::soa;
244+
using Base = Struct<Container>;
245+
246+
constexpr Wrapper() = default;
247+
constexpr Wrapper(Base b) : Base{static_cast<Base&&>(b)} {}
248+
249+
template <template <class> class OtherContainer>
250+
requires random_access_like<OtherContainer>
251+
constexpr Wrapper(const Struct<OtherContainer>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
252+
253+
constexpr Wrapper<Struct, const_reference> operator[] (size_t i) const { return Base::apply(RandomAccessAt<Struct<const_reference>>{i}); }
254+
constexpr Wrapper<Struct, const_reference> operator*() const { return operator[](0); }
255+
constexpr Wrapper<Struct, const_reference> operator->() const { return operator[](0); }
256+
257+
constexpr bool operator==(const Wrapper& other) const { return Base::apply(FirstMember{}) == other.apply(FirstMember{}); }
258+
constexpr bool operator!=(const Wrapper& other) const { return !this->operator==(other); }
259+
constexpr bool operator<(const Wrapper& other) const { return Base::apply(FirstMember{}) < other.apply(FirstMember{}); }
260+
261+
constexpr Wrapper operator+(ptrdiff_t i) const { return Base::apply(Advance<Base>{i}); }
262+
constexpr Wrapper operator-(ptrdiff_t i) const { return operator+(-i); }
263+
constexpr ptrdiff_t operator-(const Wrapper& other) const { return Base::apply(FirstMember{}) - other.apply(FirstMember{}); }
264+
265+
constexpr Wrapper& operator++() { Base::apply(PreIncrement<Base>{}); return *this; }
266+
constexpr Wrapper& operator+=(ptrdiff_t i) { return *this = *this + i; }
267+
constexpr Wrapper& operator--() { Base::apply(PreDecrement<Base>{}); return *this; }
268+
constexpr Wrapper& operator-=(ptrdiff_t i) { return *this = *this - i; }
151269
};
152270

153271
template <template <template <class> class> class Struct>
@@ -205,72 +323,17 @@ struct Wrapper<Struct, const_reference, Layout::soa> : public Struct<const_refer
205323
constexpr const_pointer<Wrapper<Struct, const_reference>> operator->() const { return this; }
206324
};
207325

208-
template <template <template <class> class> class Struct>
209-
struct Wrapper<Struct, pointer, Layout::soa> : public Struct<pointer> {
210-
using Base = Struct<pointer>;
211-
212-
constexpr Wrapper() = default;
213-
constexpr Wrapper(Base b) : Base{static_cast<Base&&>(b)} {}
214-
215-
constexpr Wrapper<Struct, reference> operator[] (size_t i) { return Base::apply(RandomAccessAt<Struct<reference>>{i}); }
216-
constexpr const Wrapper<Struct, const_reference> operator[] (size_t i) const { return Base::apply(RandomAccessAt<Struct<const_reference>>{i}); }
217-
218-
constexpr Wrapper<Struct, reference> operator*() { return operator[](0); }
219-
constexpr Wrapper<Struct, const_reference> operator*() const { return operator[](0); }
220-
constexpr Wrapper<Struct, reference> operator->() { return operator[](0); }
221-
constexpr Wrapper<Struct, const_reference> operator->() const { return operator[](0); }
222-
223-
constexpr bool operator==(const Wrapper& other) const { return Base::apply(FirstMember{}) == other.apply(FirstMember{}); }
224-
constexpr bool operator!=(const Wrapper& other) const { return !this->operator==(other); }
225-
constexpr bool operator<(const Wrapper& other) const { return Base::apply(FirstMember{}) < other.apply(FirstMember{}); }
226-
227-
constexpr Wrapper operator+(ptrdiff_t i) const { return Base::apply(Advance<Base>{i}); }
228-
constexpr Wrapper operator-(ptrdiff_t i) const { return operator+(-i); }
229-
constexpr ptrdiff_t operator-(const Wrapper& other) const { return Base::apply(FirstMember{}) - other.apply(FirstMember{}); }
230-
231-
constexpr Wrapper& operator++() { Base::apply(PreIncrement<Base>{}); return *this; }
232-
constexpr Wrapper& operator+=(ptrdiff_t i) { return *this = *this + i; }
233-
constexpr Wrapper& operator--() { Base::apply(PreDecrement<Base>{}); return *this; }
234-
constexpr Wrapper& operator-=(ptrdiff_t i) { return *this = *this - i; }
235-
};
236-
237-
template <template <template <class> class> class Struct>
238-
struct Wrapper<Struct, const_pointer, Layout::soa> : public Struct<const_pointer> {
239-
using Base = Struct<const_pointer>;
240-
241-
constexpr Wrapper() = default;
242-
constexpr Wrapper(Base b) : Base{static_cast<Base&&>(b)} {}
243-
constexpr Wrapper(const Struct<pointer>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
244-
245-
constexpr Wrapper<Struct, const_reference> operator[] (size_t i) const { return Base::apply(RandomAccessAt<Struct<const_reference>>{i}); }
246-
constexpr Wrapper<Struct, const_reference> operator*() const { return operator[](0); }
247-
constexpr Wrapper<Struct, const_reference> operator->() const { return operator[](0); }
248-
249-
constexpr bool operator==(const Wrapper& other) const { return Base::apply(FirstMember{}) == other.apply(FirstMember{}); }
250-
constexpr bool operator!=(const Wrapper& other) const { return !this->operator==(other); }
251-
constexpr bool operator<(const Wrapper& other) const { return Base::apply(FirstMember{}) < other.apply(FirstMember{}); }
252-
253-
constexpr Wrapper operator+(ptrdiff_t i) const { return Base::apply(Advance<Base>{i}); }
254-
constexpr Wrapper operator-(ptrdiff_t i) const { return operator+(-i); }
255-
constexpr ptrdiff_t operator-(const Wrapper& other) const { return Base::apply(FirstMember{}) - other.apply(FirstMember{}); }
256-
257-
constexpr Wrapper& operator++() { Base::apply(PreIncrement<Base>{}); return *this; }
258-
constexpr Wrapper& operator+=(ptrdiff_t i) { return *this = *this + i; }
259-
constexpr Wrapper& operator--() { Base::apply(PreDecrement<Base>{}); return *this; }
260-
constexpr Wrapper& operator-=(ptrdiff_t i) { return *this = *this - i; }
261-
};
262-
263326
} // namespace memlayout
264327

265-
#define WRAPPER_APPLY_UNARY(...)\
328+
#define MEMLAYOUT_APPLY_UNARY(...)\
266329
template <class Function>\
267330
constexpr auto apply(Function&& f) { return f(__VA_ARGS__); }\
268331
template <class Function>\
269332
constexpr auto apply(Function&& f) const { return f(__VA_ARGS__); }\
270333

271-
#define WRAPPER_EXPAND(m) f(m, other.m)
334+
#define MEMLAYOUT_EXPAND(m) f(m, other.m)
272335

273-
#define WRAPPER_APPLY_BINARY(STRUCT_NAME, ...)\
336+
#define MEMLAYOUT_APPLY_BINARY(STRUCT_NAME, ...)\
274337
template <template <class> class other_Container, class Function>\
275338
constexpr STRUCT_NAME apply(STRUCT_NAME<other_Container>& other, Function&& f) { return {__VA_ARGS__}; }\
276339
template <template <class> class other_Container, class Function>\
@@ -280,4 +343,4 @@ struct Wrapper<Struct, const_pointer, Layout::soa> : public Struct<const_pointer
280343
template <template <class> class other_Container, class Function>\
281344
constexpr STRUCT_NAME apply(const STRUCT_NAME<other_Container>& other, Function&& f) const { return {__VA_ARGS__}; }\
282345

283-
#endif // WRAPPER_H
346+
#endif // MEMLAYOUT_H

tests/include/structs.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ namespace test {
77

88
template <template <class> class Container>
99
struct Point2D {
10-
WRAPPER_APPLY_UNARY(x, y)
11-
WRAPPER_APPLY_BINARY(Point2D, WRAPPER_EXPAND(x), WRAPPER_EXPAND(y))
10+
MEMLAYOUT_APPLY_UNARY(x, y)
11+
MEMLAYOUT_APPLY_BINARY(Point2D, MEMLAYOUT_EXPAND(x), MEMLAYOUT_EXPAND(y))
1212

1313
Container<int32_t> x, y;
1414
constexpr int32_t abs2() const { return x * x + y * y; }
1515
};
1616

1717
template <template <class> class Container>
1818
struct Point3D {
19-
WRAPPER_APPLY_UNARY(point2d, z)
20-
WRAPPER_APPLY_BINARY(Point3D, WRAPPER_EXPAND(point2d), WRAPPER_EXPAND(z))
19+
MEMLAYOUT_APPLY_UNARY(point2d, z)
20+
MEMLAYOUT_APPLY_BINARY(Point3D, MEMLAYOUT_EXPAND(point2d), MEMLAYOUT_EXPAND(z))
2121

2222
memlayout::Wrapper<Point2D, Container> point2d;
2323
Container<int32_t> z;
@@ -30,8 +30,8 @@ struct Point3D {
3030

3131
template <template <class> class Container>
3232
struct Gaussian {
33-
WRAPPER_APPLY_UNARY(mean, covariance)
34-
WRAPPER_APPLY_BINARY(Gaussian, WRAPPER_EXPAND(mean), WRAPPER_EXPAND(covariance))
33+
MEMLAYOUT_APPLY_UNARY(mean, covariance)
34+
MEMLAYOUT_APPLY_BINARY(Gaussian, MEMLAYOUT_EXPAND(mean), MEMLAYOUT_EXPAND(covariance))
3535

3636
memlayout::Wrapper<Point3D, Container> mean;
3737
Container<uint16_t[3][3]> covariance;

0 commit comments

Comments
 (0)