@@ -12,29 +12,34 @@ template <class T> using const_reference = const T&;
1212template <class T > using pointer = T*;
1313template <class T > using const_pointer = const T*;
1414
15+ template <class T > using reference_restrict = T& __restrict__;
16+ template <class T > using const_reference_restrict = const T& __restrict__;
17+ template <class T > using pointer_restrict = T* __restrict__;
18+ template <class T > using const_pointer_restrict = const T* __restrict__;
19+
1520template <class SF >
1621struct RandomAccessAt {
1722 MemLayout::size_t i;
1823 template <class ... Args>
19- constexpr SF operator ()(Args& ...args) const { return {{ args[i]...} }; }
24+ constexpr SF operator ()(Args& ...args) const { return {args[i]...}; }
2025 template <class ... Args>
21- constexpr SF operator ()(const Args& ...args) const { return {{ args[i]...} }; }
26+ constexpr SF operator ()(const Args& ...args) const { return {args[i]...}; }
2227};
2328
2429template <class SF >
2530struct GetPointer {
2631 template <class ... Args>
27- constexpr SF operator ()(Args& ...args) const { return {{ &args...} }; }
32+ constexpr SF operator ()(Args& ...args) const { return {&args...}; }
2833 template <class ... Args>
29- constexpr SF operator ()(const Args& ...args) const { return {{ &args...} }; }
34+ constexpr SF operator ()(const Args& ...args) const { return {&args...}; }
3035};
3136
3237template <class SF >
3338struct AggregateConstructor {
3439 template <class ... Args>
35- constexpr SF operator ()(Args& ...args) const { return {{ args...} }; }
40+ constexpr SF operator ()(Args& ...args) const { return {args...}; }
3641 template <class ... Args>
37- constexpr SF operator ()(const Args& ...args) const { return {{ args...}} ; }
42+ constexpr SF operator ()(const Args& ...args) const { return {args...}; }
3843};
3944
4045struct FirstMember {
@@ -47,20 +52,20 @@ struct FirstMember {
4752template <class SF >
4853struct PreIncrement {
4954 template <class ... Args>
50- constexpr SF operator ()(Args& ...args) const { return {{ ++args...} }; }
55+ constexpr SF operator ()(Args& ...args) const { return {++args...}; }
5156};
5257
5358template <class SF >
5459struct PreDecrement {
5560 template <class ... Args>
56- constexpr SF operator ()(Args& ...args) const { return {{ --args...} }; }
61+ constexpr SF operator ()(Args& ...args) const { return {--args...}; }
5762};
5863
5964template <class SF >
6065struct Advance {
6166 ptrdiff_t i;
6267 template <class ... Args>
63- constexpr SF operator ()(const Args& ...args) const { return {{ (args + i)...} }; }
68+ constexpr SF operator ()(const Args& ...args) const { return {(args + i)...}; }
6469};
6570
6671struct CopyAssignment {
@@ -78,10 +83,12 @@ struct wrapper : public S<F> {
7883 constexpr wrapper () = default;
7984 constexpr wrapper (Base b) : Base{static_cast <Base&&>(b)} {}
8085 template <template <class > class F_other >
81- constexpr wrapper (wrapper<S, F_other>& other) : Base{other.apply (AggregateConstructor<wrapper>{})} {}
86+ constexpr wrapper (S<F_other>& other) : Base{other.apply (AggregateConstructor<Base>{})} {}
87+ template <template <class > class F_other >
88+ constexpr wrapper (const S<F_other>& other) : Base{other.apply (AggregateConstructor<Base>{})} {}
8289
83- constexpr wrapper<S, reference> operator [] (size_t i) { return Base::apply (RandomAccessAt<wrapper<S, reference>>{i}); }
84- constexpr wrapper<S, const_reference> operator [] (size_t i) const { return Base::apply (RandomAccessAt<wrapper<S, const_reference>>{i}); }
90+ constexpr wrapper<S, reference> operator [] (size_t i) { return Base::apply (RandomAccessAt<S< reference>>{i}); }
91+ constexpr wrapper<S, const_reference> operator [] (size_t i) const { return Base::apply (RandomAccessAt<S< const_reference>>{i}); }
8592
8693 constexpr wrapper<S, reference> operator *() { return operator [](0 ); }
8794 constexpr wrapper<S, const_reference> operator *(ptrdiff_t ) const { return operator [](0 ); }
@@ -93,8 +100,8 @@ struct wrapper<S, value> : public S<value> {
93100
94101 constexpr wrapper () = default;
95102 constexpr wrapper (Base b) : Base{static_cast <Base&&>(b)} {}
96- constexpr wrapper (wrapper<S, reference> other) : Base(other.apply(AggregateConstructor<wrapper >{})) {}
97- constexpr wrapper (wrapper<S, const_reference> other) : Base(other.apply(AggregateConstructor<wrapper >{})) {}
103+ constexpr wrapper (const S< reference>& other) : Base(other.apply(AggregateConstructor<Base >{})) {}
104+ constexpr wrapper (const S< const_reference>& other) : Base(other.apply(AggregateConstructor<Base >{})) {}
98105
99106 // constexpr S<MemLayout::pointer> operator& () { return apply(GetPointer<S<MemLayout::pointer>>{}); }
100107 // constexpr S<MemLayout::const_pointer> operator& () const { return apply(GetPointer<S<MemLayout::const_pointer>>{}); }
@@ -106,10 +113,15 @@ struct wrapper<S, reference> : public S<reference> {
106113
107114 constexpr wrapper () = delete;
108115 constexpr wrapper (Base b) : Base{static_cast <Base&&>(b)} {}
109- constexpr wrapper (wrapper<S, value>& other) : Base(other.apply(AggregateConstructor<wrapper>{})) {}
116+ constexpr wrapper (S<value>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
117+ constexpr wrapper (S<reference_restrict> other) : Base(other.apply(AggregateConstructor<Base>{})) {}
110118
111119 constexpr wrapper (const wrapper& other) = default;
112120
121+ constexpr wrapper& operator =(const wrapper<S, value>& other) {
122+ Base::apply (other, CopyAssignment{});
123+ return *this ;
124+ }
113125 constexpr wrapper& operator =(const wrapper& other) {
114126 Base::apply (other, CopyAssignment{});
115127 return *this ;
@@ -118,17 +130,63 @@ struct wrapper<S, reference> : public S<reference> {
118130 Base::apply (other, CopyAssignment{});
119131 return *this ;
120132 }
133+ constexpr wrapper& operator =(const wrapper<S, reference_restrict>& other) {
134+ Base::apply (other, CopyAssignment{});
135+ return *this ;
136+ }
137+ constexpr wrapper& operator =(const wrapper<S, const_reference_restrict>& other) {
138+ Base::apply (other, CopyAssignment{});
139+ return *this ;
140+ }
141+
142+ constexpr wrapper (wrapper&& other) = default;
143+
144+ constexpr wrapper& operator =(wrapper&& other) { return operator =(other); }
145+
146+ constexpr wrapper<S, pointer> operator &() { return Base::apply (GetPointer<S<pointer>>{}); }
147+ // constexpr wrapper<S, const_pointer> operator&() const { return Base::apply(GetPointer<S<const_pointer>>{}); }
148+ constexpr pointer<wrapper<S, reference>> operator ->() { return this ; }
149+ };
150+
151+ template <template <template <class > class > class S >
152+ struct wrapper <S, reference_restrict> : public S<reference_restrict> {
153+ using Base = S<reference_restrict>;
154+
155+ constexpr wrapper () = delete;
156+ constexpr wrapper (Base b) : Base{static_cast <Base&&>(b)} {}
157+ constexpr wrapper (S<value>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
158+ constexpr wrapper (S<reference> other) : Base(other.apply(AggregateConstructor<Base>{})) {}
159+
160+ constexpr wrapper (const wrapper& other) = default;
161+
121162 constexpr wrapper& operator =(const wrapper<S, value>& other) {
122163 Base::apply (other, CopyAssignment{});
123164 return *this ;
124165 }
166+ constexpr wrapper& operator =(const wrapper& other) {
167+ Base::apply (other, CopyAssignment{});
168+ return *this ;
169+ }
170+ constexpr wrapper& operator =(const wrapper<S, reference>& other) {
171+ Base::apply (other, CopyAssignment{});
172+ return *this ;
173+ }
174+ constexpr wrapper& operator =(const wrapper<S, const_reference>& other) {
175+ Base::apply (other, CopyAssignment{});
176+ return *this ;
177+ }
178+ constexpr wrapper& operator =(const wrapper<S, const_reference_restrict>& other) {
179+ Base::apply (other, CopyAssignment{});
180+ return *this ;
181+ }
125182
126183 constexpr wrapper (wrapper&& other) = default;
127184
128185 constexpr wrapper& operator =(wrapper&& other) { return operator =(other); }
129186
130- constexpr wrapper<S, pointer> operator & () { return Base::apply (GetPointer<wrapper<S, pointer>>{}); }
131- // constexpr wrapper<S, const_pointer> operator& () const { return Base::apply(GetPointer<wrapper<S, const_pointer>>{}); }
187+ constexpr wrapper<S, pointer> operator &() { return Base::apply (GetPointer<S<pointer>>{}); }
188+ // constexpr wrapper<S, const_pointer> operator&() const { return Base::apply(GetPointer<S<const_pointer>>{}); }
189+ constexpr pointer<wrapper<S, reference>> operator ->() { return this ; }
132190};
133191
134192template <template <template <class > class > class S >
@@ -137,10 +195,28 @@ struct wrapper<S, const_reference> : public S<const_reference> {
137195
138196 constexpr wrapper () = delete;
139197 constexpr wrapper (Base b) : Base{static_cast <Base&&>(b)} {}
140- constexpr wrapper (wrapper<S, value> other) : Base(other.apply(AggregateConstructor<wrapper>{})) {}
141- constexpr wrapper (wrapper<S, reference> other) : Base(other.apply(AggregateConstructor<wrapper>{})) {}
198+ constexpr wrapper (const S<value>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
199+ constexpr wrapper (const S<reference>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
200+ constexpr wrapper (const S<reference_restrict>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
201+ constexpr wrapper (const S<const_reference_restrict>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
142202
143- constexpr wrapper<S, const_pointer> operator &() const { return Base::apply (GetPointer<wrapper<S, const_pointer>>{}); }
203+ constexpr wrapper<S, const_pointer> operator &() const { return Base::apply (GetPointer<S<const_pointer>>{}); }
204+ constexpr const_pointer<wrapper<S, const_reference>> operator ->() const { return this ; }
205+ };
206+
207+ template <template <template <class > class > class S >
208+ struct wrapper <S, const_reference_restrict> : public S<const_reference_restrict> {
209+ using Base = S<const_reference_restrict>;
210+
211+ constexpr wrapper () = delete;
212+ constexpr wrapper (Base b) : Base{static_cast <Base&&>(b)} {}
213+ constexpr wrapper (const S<value>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
214+ constexpr wrapper (const S<reference>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
215+ constexpr wrapper (const S<reference_restrict>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
216+ constexpr wrapper (const S<const_reference>& other) : Base(other.apply(AggregateConstructor<Base>{})) {}
217+
218+ constexpr wrapper<S, const_pointer> operator &() const { return Base::apply (GetPointer<S<const_pointer>>{}); }
219+ constexpr const_pointer<wrapper<S, const_reference>> operator ->() const { return this ; }
144220};
145221
146222template <template <template <class > class > class S >
@@ -150,23 +226,25 @@ struct wrapper<S, pointer> : public S<pointer> {
150226 constexpr wrapper () = default;
151227 constexpr wrapper (Base b) : Base{static_cast <Base&&>(b)} {}
152228
153- constexpr wrapper<S, reference> operator [] (size_t i) { return Base::apply (RandomAccessAt<wrapper<S, reference>>{i}); }
154- constexpr wrapper<S, const_reference> operator [] (size_t i) const { return Base::apply (RandomAccessAt<wrapper<S, const_reference>>{i}); }
229+ constexpr wrapper<S, reference> operator [] (size_t i) { return Base::apply (RandomAccessAt<S< reference>>{i}); }
230+ constexpr const wrapper<S, const_reference> operator [] (size_t i) const { return Base::apply (RandomAccessAt<S< const_reference>>{i}); }
155231
156232 constexpr wrapper<S, reference> operator *() { return operator [](0 ); }
157233 constexpr wrapper<S, const_reference> operator *() const { return operator [](0 ); }
234+ constexpr wrapper<S, reference> operator ->() { return operator [](0 ); }
235+ constexpr wrapper<S, const_reference> operator ->() const { return operator [](0 ); }
158236
159237 constexpr bool operator ==(const wrapper& other) const { return Base::apply (FirstMember{}) == other.apply (FirstMember{}); }
160238 constexpr bool operator !=(const wrapper& other) const { return !this ->operator ==(other); }
161239 constexpr bool operator <(const wrapper& other) const { return Base::apply (FirstMember{}) < other.apply (FirstMember{}); }
162240
163- constexpr wrapper operator +(ptrdiff_t i) const { return Base::apply (Advance<wrapper >{i}); }
241+ constexpr wrapper operator +(ptrdiff_t i) const { return Base::apply (Advance<Base >{i}); }
164242 constexpr wrapper operator -(ptrdiff_t i) const { return operator +(-i); }
165243 constexpr ptrdiff_t operator -(const wrapper& other) const { return Base::apply (FirstMember{}) - other.apply (FirstMember{}); }
166244
167- constexpr wrapper& operator ++() { Base::apply (PreIncrement<wrapper >{}); return *this ; }
245+ constexpr wrapper& operator ++() { Base::apply (PreIncrement<Base >{}); return *this ; }
168246 constexpr wrapper& operator +=(ptrdiff_t i) { return *this = *this + i; }
169- constexpr wrapper& operator --() { Base::apply (PreDecrement<wrapper >{}); return *this ; }
247+ constexpr wrapper& operator --() { Base::apply (PreDecrement<Base >{}); return *this ; }
170248 constexpr wrapper& operator -=(ptrdiff_t i) { return *this = *this - i; }
171249};
172250
@@ -176,10 +254,24 @@ struct wrapper<S, const_pointer> : public S<const_pointer> {
176254
177255 constexpr wrapper () = default;
178256 constexpr wrapper (Base b) : Base{static_cast <Base&&>(b)} {}
179- constexpr wrapper (wrapper<S, pointer> other) : Base(other.apply(AggregateConstructor<wrapper >{})) {}
257+ constexpr wrapper (const S< pointer>& other) : Base(other.apply(AggregateConstructor<Base >{})) {}
180258
181- constexpr wrapper<S, const_reference> operator [] (size_t i) const { return Base::apply (RandomAccessAt<wrapper<S, const_reference>>{i}); }
259+ constexpr wrapper<S, const_reference> operator [] (size_t i) const { return Base::apply (RandomAccessAt<S< const_reference>>{i}); }
182260 constexpr wrapper<S, const_reference> operator *() const { return operator [](0 ); }
261+ constexpr wrapper<S, const_reference> operator ->() const { return operator [](0 ); }
262+
263+ constexpr bool operator ==(const wrapper& other) const { return Base::apply (FirstMember{}) == other.apply (FirstMember{}); }
264+ constexpr bool operator !=(const wrapper& other) const { return !this ->operator ==(other); }
265+ constexpr bool operator <(const wrapper& other) const { return Base::apply (FirstMember{}) < other.apply (FirstMember{}); }
266+
267+ constexpr wrapper operator +(ptrdiff_t i) const { return Base::apply (Advance<Base>{i}); }
268+ constexpr wrapper operator -(ptrdiff_t i) const { return operator +(-i); }
269+ constexpr ptrdiff_t operator -(const wrapper& other) const { return Base::apply (FirstMember{}) - other.apply (FirstMember{}); }
270+
271+ constexpr wrapper& operator ++() { Base::apply (PreIncrement<Base>{}); return *this ; }
272+ constexpr wrapper& operator +=(ptrdiff_t i) { return *this = *this + i; }
273+ constexpr wrapper& operator --() { Base::apply (PreDecrement<Base>{}); return *this ; }
274+ constexpr wrapper& operator -=(ptrdiff_t i) { return *this = *this - i; }
183275};
184276
185277enum Flag { soa, aos };
@@ -204,6 +296,10 @@ struct interface<S, F, Flag::soa> { using type = wrapper<S, F>; };
204296#define MEMLAYOUT_EXPAND (m ) f(m, other.m)
205297
206298#define MEMLAYOUT_APPLY_BINARY (STRUCT_NAME, ...)\
299+ template <template <class > class F_other , class Function >\
300+ constexpr STRUCT_NAME apply (STRUCT_NAME<F_other>& other, Function&& f) { return {__VA_ARGS__}; }\
301+ template <template <class > class F_other , class Function >\
302+ constexpr STRUCT_NAME apply (STRUCT_NAME<F_other>& other, Function&& f) const { return {__VA_ARGS__}; }\
207303 template <template <class > class F_other , class Function >\
208304 constexpr STRUCT_NAME apply (const STRUCT_NAME<F_other>& other, Function&& f) { return {__VA_ARGS__}; }\
209305 template <template <class > class F_other , class Function >\
0 commit comments