Предположим, мне нужно хранить некоторые данные, состоящие из n Foo
s, n Bar
s и n Baz
s.Элементы соответствующих индексов связаны между собой, поэтому вы также можете рассматривать эти данные как n триплетов Foo
, Bar and
Baz`.Первое описание данных - это «структура массивов», второе - «массив структур»;вы можете найти обсуждение этих двух макетов здесь, в StackOverflow.
Теперь, если мы знаем n во время компиляции, ваши файдеры довольно легко выражают оба восприятия в C ++.
Массив структур (AoS):
struct {
Foo foo;
Bar bar;
Baz baz;
} aos_form[n];
Структура массивов (SoA):
struct {
Foo foo[n];
Bar bar[n];
Baz baz[n];
} soa_form;
но обратите внимание, что мы уже нарушаем принцип СУХОЙ, когда говоримn
3 раза.Это значительно усугубляется, если мы теперь хотим динамически распределять память для наших данных - скажем, с помощью std::unique_ptr
s:
Array of Structures (AoS):
struct {
Foo foo;
Bar bar;
Baz baz;
} data_tuple_t;
auto aos_form = std::make_unique<data_tuple_t[]>(n);
достаточно разумно, хотя мыпохоже, сейчас нужно определение типа.Но как насчет SoA?Ну,
Структура массивов (SoA):
struct {
std::unique_ptr<Foo[]> foo;
std::unique_ptr<Bar[]> bar;
std::unique_ptr<Bas[]> baz;
} soa_form = {
std::make_unique<Foo[]>(n),
std::make_unique<Bar[]>(n),
std::make_unique<Baz[]>(n)
}
Теперь это просто ужасно!Мы повторяем себя тремя различными способами:
- Задание типа поля дважды - в определении типа и в присваивании
- Необходимость быть "многословным", а не "непрозрачным" или "неявный "как в определении, так и в инициализации.
- Необходимость указать длину трижды.
Кроме написания специально настроенного класса, что я могу сделать проще и в целом, чтобы сделатьСоа ФОРМА "легче на глазах" (и на пальцах)?