OpenLB 1.7
Loading...
Searching...
No Matches
fieldArrayD.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2020 Adrian Kummerlaender
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24#ifndef FIELD_ARRAY_D_H
25#define FIELD_ARRAY_D_H
26
27#include "meta.h"
28#include "vector.h"
29#include "columnVector.h"
30#include "serializer.h"
32
33#include "platform/platform.h"
34
35#include <memory>
36#include <tuple>
37
38namespace olb {
39
40
42template<typename T, typename DESCRIPTOR, typename FIELD>
43using FieldD = Vector<
44 typename FIELD::template value_type<T>,
45 DESCRIPTOR::template size<FIELD>()
46>;
47
49template<typename T, typename DESCRIPTOR, typename FIELD>
51private:
52 virtual const typename FIELD::template column_type<T>& getAbstractColumn(unsigned iDim) const = 0;
53 virtual typename FIELD::template column_type<T>& getAbstractColumn(unsigned iDim) = 0;
54
55public:
56 class const_ptr;
57 class ptr;
58
59 const auto& operator[](unsigned iDim) const
60 {
61 return getAbstractColumn(iDim);
62 }
63
64 auto& operator[](unsigned iDim)
65 {
66 return getAbstractColumn(iDim);
67 }
68
69 auto get(std::size_t i) const
70 {
71 if constexpr (DESCRIPTOR::template size<FIELD>() == 1) {
72 return operator[](0)[i];
73 } else {
75 DESCRIPTOR::template size<FIELD>()>([this,i](unsigned iD) {
76 return operator[](iD)[i];
77 });
78 }
79 }
80
81 void set(std::size_t i, const FieldD<T,DESCRIPTOR,FIELD>& data)
82 {
83 for (unsigned iD=0; iD < DESCRIPTOR::template size<FIELD>(); ++iD) {
84 operator[](iD)[i] = data[iD];
85 }
86 }
87
88 const_ptr getPointer(std::size_t i) const
89 {
90 return const_ptr(*this, i);
91 }
92
93 ptr getPointer(std::size_t i)
94 {
95 return ptr(*this, i);
96 }
97
98 virtual void resize(std::size_t newCount) = 0;
99
100 virtual void setProcessingContext(ProcessingContext context) = 0;
101
102};
103
105template<typename T, typename DESCRIPTOR, typename FIELD>
106class AbstractFieldArrayD<T,DESCRIPTOR,FIELD>::const_ptr
107 : public ScalarVector<const typename FIELD::template value_type<T>,
108 DESCRIPTOR::template size<FIELD>(),
109 const_ptr> {
110private:
112 std::size_t _index;
113
115 DESCRIPTOR::template size<FIELD>(),
116 const_ptr>::type;
117
118protected:
119 const typename FIELD::template value_type<T>* getComponentPointer(unsigned iDim) const
120 {
121 return &_data[iDim][_index];
122 }
123
124public:
125 const_ptr(const AbstractFieldArrayD<T,DESCRIPTOR,FIELD>& data, std::size_t index):
126 _data(data),
127 _index(index) { }
128
130 _data(rhs._data),
131 _index(rhs._index) { }
132
133 std::size_t getIndex() const
134 {
135 return _index;
136 }
137
138 void setIndex(std::size_t index)
139 {
140 _index = index;
141 }
142
143};
144
146template<typename T, typename DESCRIPTOR, typename FIELD>
147class AbstractFieldArrayD<T,DESCRIPTOR,FIELD>::ptr
148 : public ScalarVector<typename FIELD::template value_type<T>,
149 DESCRIPTOR::template size<FIELD>(),
150 ptr> {
151private:
153 std::size_t _index;
154
156 DESCRIPTOR::template size<FIELD>(),
157 ptr>::type;
158
159protected:
160 const typename FIELD::template value_type<T>* getComponentPointer(unsigned iDim) const
161 {
162 return &_data[iDim][_index];
163 }
164
165 typename FIELD::template value_type<T>* getComponentPointer(unsigned iDim)
166 {
167 return &_data[iDim][_index];
168 }
169
170public:
172 _data(data),
173 _index(index) { }
174
175 ptr(ptr&& rhs):
176 _data(rhs._data),
177 _index(rhs._index) { }
178
179 template <typename U, typename IMPL>
180 ptr& operator=(const GenericVector<U,DESCRIPTOR::template size<FIELD>(),IMPL>& rhs)
181 {
182 for (unsigned iD=0; iD < DESCRIPTOR::template size<FIELD>(); ++iD) {
183 this->operator[](iD) = rhs[iD];
184 }
185 return *this;
186 }
187
188 std::size_t getIndex() const
189 {
190 return _index;
191 }
192
193 void setIndex(std::size_t index)
194 {
195 _index = index;
196 }
197
198};
199
200
202template<typename T, typename DESCRIPTOR, Platform PLATFORM, typename FIELD>
203class FieldArrayD final : public ColumnVector<typename ImplementationOf<typename FIELD::template column_type<T>,PLATFORM>::type,
204 DESCRIPTOR::template size<FIELD>()>
205 , public AbstractFieldArrayD<T,DESCRIPTOR,FIELD>
206{
207private:
208 const typename FIELD::template column_type<T>& getAbstractColumn(unsigned iDim) const override
209 {
210 return this->operator[](iDim);
211 }
212
213 typename FIELD::template column_type<T>& getAbstractColumn(unsigned iDim) override
214 {
215 return this->operator[](iDim);
216 }
217
218public:
219 using field_t = FIELD;
220 using value_type = typename FIELD::template value_type<T>;
222
223 using ColumnVector<column_type,DESCRIPTOR::template size<FIELD>()>::operator[];
224
225 FieldArrayD(std::size_t count):
227 DESCRIPTOR::template size<FIELD>()>(count)
228 {
229 const auto initial = FIELD::template getInitialValue<T,DESCRIPTOR>();
230 for (std::size_t i=0; i < count; ++i) {
231 this->getRowPointer(i) = initial;
232 }
233 }
234
236 {
237 return static_cast<const AbstractFieldArrayD<T,DESCRIPTOR,FIELD>&>(*this);
238 }
239
244
246 {
247 for (unsigned iDim=0; iDim < DESCRIPTOR::template size<FIELD>(); ++iDim) {
248 this->operator[](iDim).setProcessingContext(context);
249 }
250 }
251
252 void resize(std::size_t newCount) override {
253 const std::size_t oldCount = this->_count;
254 static_cast<ColumnVector<
256 DESCRIPTOR::template size<FIELD>()
257 >*>(this)->resize(newCount);
258 if (oldCount < newCount) {
259 const auto initial = FIELD::template getInitialValue<T,DESCRIPTOR>();
260 for (std::size_t i=oldCount; i < newCount; ++i) {
261 this->getRowPointer(i) = initial;
262 }
263 }
264 }
265
267 auto getField(std::size_t iCell) const
268 {
269 return this->getRow(iCell);
270 }
271
273 void setField(std::size_t iCell, const FieldD<T,DESCRIPTOR,FIELD>& v)
274 {
275 this->setRow(iCell, v);
276 }
277
278 auto getFieldPointer(std::size_t iCell) const
279 {
280 return this->getRowPointer(iCell);
281 }
282 auto getFieldPointer(std::size_t iCell)
283 {
284 return this->getRowPointer(iCell);
285 }
286
287};
288
290template <typename T, typename DESCRIPTOR, typename FIELD>
292
294
295template <Platform PLATFORM>
297
298};
299
300
301template <typename T, typename DESCRIPTOR, Platform PLATFORM, typename FIELD>
302class ConcreteCommunicatable<FieldArrayD<T,DESCRIPTOR,PLATFORM,FIELD>> final : public Communicatable {
303private:
305
306public:
308 _communicatee{communicatee} { }
309
311 std::size_t size(ConstSpan<CellID> indices) const override
312 {
314 ColumnVector<typename ImplementationOf<typename FIELD::template column_type<T>,PLATFORM>::type,
315 DESCRIPTOR::template size<FIELD>()>
316 >(_communicatee).size(indices));
317 }
318
320 std::size_t serialize(ConstSpan<CellID> indices,
321 std::uint8_t* buffer) const override
322 {
323 std::uint8_t* curr = buffer;
326 DESCRIPTOR::template size<FIELD>()>
327 >(_communicatee).serialize(indices, curr);
328 return curr - buffer;
329 }
330
332 std::size_t deserialize(ConstSpan<CellID> indices,
333 const std::uint8_t* buffer) override
334 {
335 const std::uint8_t* curr = buffer;
338 DESCRIPTOR::template size<FIELD>()>
339 >(_communicatee).deserialize(indices, curr);
340 return curr - buffer;
341 }
342};
343
345
351template<typename T, typename DESCRIPTOR, Platform PLATFORM, typename... FIELDS>
353private:
355 std::size_t _count;
357 std::tuple<FieldArrayD<T,DESCRIPTOR,PLATFORM,FIELDS>...> _static;
358
359public:
360 using fields_t = meta::list<FIELDS...>;
361
362 MultiFieldArrayD(std::size_t count=1):
363 _count(count),
364 // Trickery to construct each member of _static with `count`.
365 // Uses the comma operator in conjunction with type dropping.
366 _static((std::void_t<FIELDS>(), count)...)
367 { }
368
369 template <typename FIELD>
371 {
372 static_assert(meta::contains<FIELD,FIELDS...>(), "FIELD not contained in FIELDS");
373 return std::get<(fields_t::template index<FIELD>())>(_static);
374 }
375
376 template <typename FIELD>
378 {
379 static_assert(meta::contains<FIELD,FIELDS...>(), "FIELD not contained in FIELDS");
380 return std::get<(fields_t::template index<FIELD>())>(_static);
381 }
382
384 template <typename FIELD>
385 auto getField(std::size_t iCell) const
386 {
387 return get<FIELD>().getRow(iCell);
388 }
389
391 template <typename FIELD>
392 void setField(std::size_t iCell, const FieldD<T,DESCRIPTOR,FIELD>& v)
393 {
394 get<FIELD>().setRow(iCell, v);
395 }
396
397 template <typename FIELD>
398 const typename FIELD::template value_type<T>& getFieldComponent(std::size_t iCell, unsigned iDim) const;
399 template <typename FIELD>
400 typename FIELD::template value_type<T>& getFieldComponent(std::size_t iCell, unsigned iDim);
401
402 template <typename FIELD>
403 auto getFieldPointer(std::size_t iCell) const
404 {
405 return get<FIELD>().getRowPointer(iCell);
406 }
407 template <typename FIELD>
408 auto getFieldPointer(std::size_t iCell)
409 {
410 return get<FIELD>().getRowPointer(iCell);
411 }
412
414 template <typename F>
415 void forFields(F f) const;
416 template <typename F>
417 void forFields(F f);
419 template <typename F>
420 void forFieldsAt(std::size_t idx, F f);
421
423
426 void resize(std::size_t newCount)
427 {
428 forFields([newCount](auto& fieldArray) {
429 fieldArray.resize(newCount);
430 });
431 _count = newCount;
432 }
433
435 void swap(std::size_t i, std::size_t j)
436 {
437 forFields([i,j](auto& fieldArray) {
438 fieldArray.swap(i,j);
439 });
440 }
441
443 forFields([context](auto& fieldArray) {
444 fieldArray.setProcessingContext(context);
445 });
446 }
447
449 std::size_t getNblock() const override;
451 std::size_t getSerializableSize() const override;
453 bool* getBlock(std::size_t iBlock, std::size_t& sizeBlock, bool loadingMode) override;
454
455};
456
457//template <typename T, typename DESCRIPTOR, Platform PLATFORM, typename FIELD>
458//ConcreteCommunicatable(FieldArrayD<T,DESCRIPTOR,PLATFORM,FIELD>&) -> ConcreteCommunicatable<
459// ColumnVector<typename ImplementationOf<typename FIELD::template column_type<T>,PLATFORM>::type,
460// DESCRIPTOR::template size<FIELD>()>
461//>;
462
463
464template <typename T, typename DESCRIPTOR, Platform PLATFORM, typename... FIELDS>
465class ConcreteCommunicatable<MultiFieldArrayD<T,DESCRIPTOR,PLATFORM,FIELDS...>> final : public Communicatable {
466private:
467 MultiFieldArrayD<T,DESCRIPTOR,PLATFORM,FIELDS...>& _communicatee;
468
469public:
471 _communicatee{communicatee} { }
472
474 std::size_t size(ConstSpan<CellID> indices) const override
475 {
477 ColumnVector<typename ImplementationOf<typename FIELDS::template column_type<T>,PLATFORM>::type,
478 DESCRIPTOR::template size<FIELDS>()>
479 >(_communicatee.template get<FIELDS>()).size(indices) + ... + 0);
480 }
481
483 std::size_t serialize(ConstSpan<CellID> indices,
484 std::uint8_t* buffer) const override
485 {
486 std::uint8_t* curr = buffer;
487 meta::list<FIELDS...>::for_each([&](auto field) {
488 using FIELD = typename decltype(field)::type;
491 DESCRIPTOR::template size<FIELD>()>
492 >(_communicatee.template get(field)).serialize(indices, curr);
493 });
494 return curr - buffer;
495 }
496
498 std::size_t deserialize(ConstSpan<CellID> indices,
499 const std::uint8_t* buffer) override
500 {
501 const std::uint8_t* curr = buffer;
502 meta::list<FIELDS...>::for_each([&](auto field) {
503 using FIELD = typename decltype(field)::type;
506 DESCRIPTOR::template size<FIELD>()>
507 >(_communicatee.template get(field)).deserialize(indices, curr);
508 });
509 return curr - buffer;
510 }
511};
512
513
515template <typename T, typename GROUPS>
517template <typename T, typename... GROUPS>
518class DynamicFieldGroupsD<T, meta::list<GROUPS...>> {
519private:
520 template <typename GROUP>
521 struct GroupedFieldArrayD {
522 template <typename... FIELDS>
523 using curried = MultiFieldArrayD<T,GROUP,Platform::CPU_SISD,FIELDS...>;
524 using type = typename GROUP::template decompose_into<curried>;
525 };
526
527 std::tuple<typename GroupedFieldArrayD<GROUPS>::type...> _data;
528
529 std::size_t _count;
530
531public:
532 DynamicFieldGroupsD(std::size_t count):
533 _data((std::void_t<GROUPS>(), count)...), _count(count) { }
534
535 template <typename GROUP>
536 auto& get() {
537 if constexpr (meta::contains<GROUP,GROUPS...>()) {
538 return std::get<descriptors::getIndexInFieldList<GROUP,GROUPS...>()>(_data);
539 } else {
540 throw std::invalid_argument("This DynamicFieldGroupsD does not provide GROUP.");
541 }
542 }
543
544 std::size_t count(){ return _count; }
545
546 void resize(std::size_t newCount) {
547 (get<GROUPS>().resize(newCount), ...);
548 _count = newCount;
549 }
550
551 void swap(std::size_t i, std::size_t j)
552 {
553 (get<GROUPS>().swap(i,j), ...);
554 }
555
556 std::size_t constexpr getSerializableSize()
557 {
558 return (get<GROUPS>().getSerializableSize() + ... + 0);
559 }
560
561};
562
563
564
565
566//Communicatable for GroupedFieldArrays
567template<typename DATA, typename... GROUPS>
569private:
570 DATA& _data;
571
572public:
574 : _data(data) {}
575
577 std::size_t size(ConstSpan<CellID> indices) const
578 {
579 std::size_t size = 0;
580 meta::list<GROUPS...>::for_each([&](auto group) {
581 using GROUP = typename decltype(group)::type;
582 // Workaround for Clang argument deduction bug
583 auto communicatable = ConcreteCommunicatable(_data.template get<GROUP>());
584 size += communicatable.size(indices);
585 });
586 return size;
587 }
588
590 std::size_t serialize(ConstSpan<CellID> indices, std::uint8_t* buffer) const
591 {
592 std::uint8_t* curr = buffer;
593 meta::list<GROUPS...>::for_each([&](auto group) {
594 using GROUP = typename decltype(group)::type;
595 // Workaround for Clang argument deduction bug
596 auto communicatable = ConcreteCommunicatable(_data.template get<GROUP>());
597 curr += communicatable.serialize(indices, curr);
598 });
599 return curr - buffer;
600 }
601
603 std::size_t deserialize(ConstSpan<CellID> indices, const std::uint8_t* buffer)
604 {
605 const std::uint8_t* curr = buffer;
606 meta::list<GROUPS...>::for_each([&](auto group) {
607 using GROUP = typename decltype(group)::type;
608 // Workaround for Clang argument deduction bug
609 auto communicatable = ConcreteCommunicatable(_data.template get<GROUP>());
610 curr += communicatable.deserialize(indices, curr);
611 });
612 return curr - buffer;
613 }
614};
615
617template <typename DATA, typename DESCRIPTOR>
619 template<typename... GROUPS>
621
622 using type = typename DESCRIPTOR::template decompose_into<CurriedFieldGroupsCommunicatable>;
623};
624
626template <typename T, typename DESCRIPTOR, Platform PLATFORM>
628 template<typename... FIELDS>
629 using CurriedMultiFieldArrayD = MultiFieldArrayD<T,DESCRIPTOR,PLATFORM,FIELDS...>;
630
631 using type = typename DESCRIPTOR::fields_t::template decompose_into<CurriedMultiFieldArrayD>;
632};
633
635template <typename T, typename DESCRIPTOR, Platform PLATFORM=Platform::CPU_SISD>
637
638
639}
640
641#endif
Read-only proxy for accessing a column vector entry.
const FIELD::template value_type< T > * getComponentPointer(unsigned iDim) const
const_ptr(const AbstractFieldArrayD< T, DESCRIPTOR, FIELD > &data, std::size_t index)
void setIndex(std::size_t index)
Proxy for accessing a column vector entry.
ptr & operator=(const GenericVector< U, DESCRIPTOR::template size< FIELD >(), IMPL > &rhs)
const FIELD::template value_type< T > * getComponentPointer(unsigned iDim) const
FIELD::template value_type< T > * getComponentPointer(unsigned iDim)
ptr(AbstractFieldArrayD< T, DESCRIPTOR, FIELD > &data, std::size_t index)
std::size_t getIndex() const
void setIndex(std::size_t index)
Platform-agnostic interface to concrete host-side field arrays.
Definition fieldArrayD.h:50
auto & operator[](unsigned iDim)
Definition fieldArrayD.h:64
const auto & operator[](unsigned iDim) const
Definition fieldArrayD.h:59
void set(std::size_t i, const FieldD< T, DESCRIPTOR, FIELD > &data)
Definition fieldArrayD.h:81
const_ptr getPointer(std::size_t i) const
Definition fieldArrayD.h:88
auto get(std::size_t i) const
Definition fieldArrayD.h:69
virtual void setProcessingContext(ProcessingContext context)=0
virtual void resize(std::size_t newCount)=0
ptr getPointer(std::size_t i)
Definition fieldArrayD.h:93
Vector of columns.
std::size_t size(ConstSpan< CellID > indices) const override
Get serialized size for data at locations indices
ConcreteCommunicatable(FieldArrayD< T, DESCRIPTOR, PLATFORM, FIELD > &communicatee)
std::size_t serialize(ConstSpan< CellID > indices, std::uint8_t *buffer) const override
Serialize data at locations indices to buffer
std::size_t deserialize(ConstSpan< CellID > indices, const std::uint8_t *buffer) override
Deserialize data at locations indices to buffer
std::size_t size(ConstSpan< CellID > indices) const override
Get serialized size for data at locations indices
std::size_t deserialize(ConstSpan< CellID > indices, const std::uint8_t *buffer) override
Deserialize data at locations indices to buffer
ConcreteCommunicatable(MultiFieldArrayD< T, DESCRIPTOR, PLATFORM, FIELDS... > &communicatee)
std::size_t serialize(ConstSpan< CellID > indices, std::uint8_t *buffer) const override
Serialize data at locations indices to buffer
std::size_t size() const
ADDITIONAL NON OVERWITTEN CALLS: Removing the necessity to provide indices.
std::size_t deserialize(ConstSpan< CellID > indices, const std::uint8_t *buffer) override
Deserialize data at locations indices to buffer
std::size_t serialize(ConstSpan< CellID > indices, std::uint8_t *buffer) const override
Serialize data at locations indices to buffer
Storage for dynamic field groups (Prototype for ParticleSystem)
SoA storage for instances of a single FIELD.
AbstractFieldArrayD< T, DESCRIPTOR, FIELD > & asAbstract()
auto getFieldPointer(std::size_t iCell) const
auto getField(std::size_t iCell) const
Return copy of FIELD data for cell iCell.
void setProcessingContext(ProcessingContext context) override
void resize(std::size_t newCount) override
const AbstractFieldArrayD< T, DESCRIPTOR, FIELD > & asAbstract() const
void setField(std::size_t iCell, const FieldD< T, DESCRIPTOR, FIELD > &v)
Set FIELD data at cell iCell.
auto getFieldPointer(std::size_t iCell)
FieldArrayD(std::size_t count)
typename FIELD::template value_type< T > value_type
typename ImplementationOf< typename FIELD::template column_type< T >, PLATFORM >::type column_type
std::size_t serialize(ConstSpan< CellID > indices, std::uint8_t *buffer) const
Serialize data at locations indices to buffer
std::size_t size(ConstSpan< CellID > indices) const
Get serialized size for data at locations indices
std::size_t deserialize(ConstSpan< CellID > indices, const std::uint8_t *buffer)
Deserialize data at locations indices to buffer
Storage for a fixed set of static FIELDS and arbitrary custom fields.
bool * getBlock(std::size_t iBlock, std::size_t &sizeBlock, bool loadingMode) override
Return a pointer to the memory of the current block and its size for the serializable interface.
MultiFieldArrayD(std::size_t count=1)
void setField(std::size_t iCell, const FieldD< T, DESCRIPTOR, FIELD > &v)
Set FIELD data at cell iCell.
auto getField(std::size_t iCell) const
Return copy of FIELD data for cell iCell.
std::size_t getSerializableSize() const override
Binary size for the serializer.
void resize(std::size_t newCount)
Change number of rows.
void swap(std::size_t i, std::size_t j)
Swap contents of rows i and j.
auto getFieldPointer(std::size_t iCell)
auto getFieldPointer(std::size_t iCell) const
const FIELD::template value_type< T > & getFieldComponent(std::size_t iCell, unsigned iDim) const
void setProcessingContext(ProcessingContext context)
void forFieldsAt(std::size_t idx, F f)
Apply generic lambda expression to each FIELD of a cell.
std::size_t getNblock() const override
Number of data blocks for the serializable interface.
const FieldArrayD< T, DESCRIPTOR, PLATFORM, FIELD > & get(meta::id< FIELD > field=meta::id< FIELD >()) const
FieldArrayD< T, DESCRIPTOR, PLATFORM, FIELD > & get(meta::id< FIELD > field=meta::id< FIELD >())
void forFields(F f) const
Apply generic expression to each FIELD array.
Base class for serializable objects of constant size. For dynamic size use BufferSerializable.
Definition serializer.h:145
Plain old scalar vector.
Definition vector.h:47
constexpr unsigned getIndexInFieldList()
constexpr bool contains()
Returns true iff a given type list contains WANTED.
Definition meta.h:125
Top level namespace for all of OpenLB.
ProcessingContext
OpenLB processing contexts.
Definition platform.h:55
Platform
OpenLB execution targets.
Definition platform.h:36
typename MultiFieldArrayForDescriptorHelper< T, DESCRIPTOR, PLATFORM >::type MultiFieldArrayForDescriptorD
MultiFieldArrayD containing each field in DESCRIPTOR::fields_t.
Base of all ColumnVector specializations.
Curried FieldArrayD template for use in callUsingConcretePlatform.
Generic vector of values supporting basic arithmetic.
static constexpr unsigned size()
Declare GroupedDataCommunicatable containing each GROUP in DESCRIPTOR::fields_t.
typename DESCRIPTOR::template decompose_into< CurriedFieldGroupsCommunicatable > type
Specializable declarator for concrete implementations of abstract storage types.
Definition column.h:52
Declare MultiFieldArrayD containing each field in DESCRIPTOR::fields_t.
typename DESCRIPTOR::fields_t::template decompose_into< CurriedMultiFieldArrayD > type
Vector of scalars.
Identity type to pass non-constructible types as value.
Definition meta.h:79
static constexpr void for_each(F f)
Calls f for each type of TYPES by-value (in reversed order!)
Definition meta.h:331
efficient implementation of a vector class