Я ищу лучшие решения о том, как организовать и получить доступ к моим данным. Мои данные - это набор структур (_array_10
и _array_20
в приведенном ниже примере), которые содержат std::array
разных размеров (см. my_data
ниже). В идеале я хотел бы получить к нему доступ, поскольку это был массив структур разной длины, но это недопустимо, поскольку разные длины имеют разные типы. Решение, которое я имею ниже, работает, но я нахожу его крайне уродливым (особенно массив void *
).
Q1. Любые идеи о том, как получить более безопасное, более эффективное / портативное или хотя бы менее уродливое решение?
Q2. Является ли предлагаемое решение без шаблонов переносимым? Он основывается на том факте, что длина хранится до остальной части данных, поскольку приведение указателя на объект с неправильной длиной приведет к нарушению доступа ко всем полям, которые идут после первого поля переменной длины.
Мои ограничения включают в себя:
- C ++ 11
- стандартные библиотеки
- no
std::vector
- использование памяти предотвращает я не могу просто выделить массив
my_data
с максимально возможной длиной - , большая часть данных (
_array_10
, _array_20
и т. д. c) будет помещена в область памяти зарезервировано специально для него
Использование data_view и шаблона требует знания длины массивов во время сборки. Было бы здорово, если бы мы могли избежать этого.
- Вопрос отредактирован, чтобы включить решение, предложенное Гийомом Рашико
#include <iostream>
#include <array>
std::array<void *, 2> _ptrs;
template <int length>
struct my_data
{
int array_length;
std::array<int, length> something;
std::array<int, length> data;
my_data()
{
array_length = length;
}
};
struct my_data_view
{
int array_length;
const int * something;
const int * data;
template <int length>
my_data_view(my_data<length> const & data_in) :
array_length(length),
something(data_in.something.data()),
data(data_in.data.data())
{}
};
template <int length>
void
print_element(int array_idx, int element)
{
my_data<length> * ptr = reinterpret_cast<my_data<length> *>(_ptrs[array_idx]);
std::cout << "array " << length << ", data[" << element << "] = " << ptr->data[element] << ".\n";
}
void
print_element(int array_idx, int element)
{
my_data<1> * ptr = reinterpret_cast<my_data<1> *>(_ptrs[array_idx]);
int length = ptr->array_length;
int data_to_print = 0;
switch (length)
{
case 10:
{
data_to_print = reinterpret_cast<my_data<10> *>(_ptrs[array_idx])->data[element];
break;
}
case 20:
{
data_to_print = reinterpret_cast<my_data<20> *>(_ptrs[array_idx])->data[element];
break;
}
}
std::cout << "array " << length << ", data[" << element << "] = " << data_to_print << ".\n";
}
void
print_element(my_data_view view, int element)
{
int length = view.array_length;
int data_to_print = view.data[element];
std::cout << "array " << length << ", data[" << element << "] = " << data_to_print << ".\n";
}
int
main()
{
my_data<10> _array_10;
my_data<20> _array_20;
_ptrs[0] = static_cast<void *>(&_array_10);
_ptrs[1] = static_cast<void *>(&_array_20);
_array_10.data[5] = 11;
_array_20.data[5] = 22;
std::cout << "using template\n";
print_element<10>(0, 5);
print_element<20>(1, 5);
std::cout << "\nwithout template\n";
print_element(0, 5);
print_element(1, 5);
std::cout << "\nusing data_view\n";
print_element(my_data_view(_array_10), 5);
print_element(my_data_view(_array_20), 5);
}