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
46namespace memlayout {
57
@@ -12,6 +14,14 @@ template <class T> using const_reference = const T&;
1214template <class T > using pointer = T*;
1315template <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+
1525template <class ReturnType >
1626struct 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+
7197enum class Layout { aos = 0 , soa = 1 };
7298
7399template <
@@ -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
130159template <
@@ -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
153271template <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
0 commit comments