Рассматривать простой старый массив данных как std::array

У нас есть большая база кода, в основном написанная на C. Мы много занимаемся числовой линейной алгеброй.

В C мы используем double* с длиной 3 для моделирования трехмерного вектора.

В C++ мы используем std:array<double,3> для моделирования трехмерного вектора.

У нас есть небольшая библиотека шаблонов для перегрузки множества операторов, таких как

template <class T, size_t N>
std::array<T, N> operator+(const std::array<T, N> &array1, const std::array<T, N> &array2) {
    std::array<T, N> a;
    for (size_t i = 0; i < N; i++) {
        a[i] = array1[i] + array2[i];
    }
    return a;
}

Проблема возникает, когда нам нужно перейти от C к C++ (в обратном направлении нет проблем, так как мы можем использовать метод .data() для доступа к выровненной памяти). Я не люблю делать копию каждого c-подобного 3D-вектора, потому что это было бы дорого в численном отношении.

Могу ли я рассматривать массив pod как std::array или есть способ инициализировать std::array таким образом, чтобы не выделялась новая память, а использовалась память из массива pod?

Я думаю об использовании gsl::span из библиотеки поддержки руководств, но мне интересно, есть ли лучшее решение.


person schorsch312    schedule 16.02.2018    source источник
comment
Является ли вариант C массивом (double[3]) или динамически выделенным (malloc(3*sizeof(double))? Вы можете взглянуть на array_view в первом случае.   -  person Henri Menke    schedule 16.02.2018


Ответы (1)


Вы можете просто произнести:

double* c_array; // assign to whatever you like, length 3 or more
auto cpp_array = reinterpret_cast<std:array<double,3>*>(c_array);

Это работает, потому что std::array определенно представляет собой не что иное, как структуру, содержащую один массив C.

person John Zwinck    schedule 16.02.2018
comment
Я согласен, что это будет работать с любой разумной реализацией стандартной библиотеки, но в стандарте ничего не гарантируется, верно? Некоторая реализация std::array может, возможно, добавить некоторые дополнительные поля отладки перед фактическим массивом... - person michalsrb; 16.02.2018
comment
Я подозреваю, что это Undefined Behavior. Да, std::array<T,N> содержит T[N]. Это не означает, что это является T[N]. А доступ к объекту через выражение несовместимого типа — это UB. - person MSalters; 16.02.2018
comment
@michalsrb: Нет, std::array не может содержать дополнительные поля отладки. При этом не только нет ничего разумного для отладки, но и широко распространенное использование std::array таким образом, который требует, чтобы он был простым внутренним массивом, никогда не позволит такой реализации добиться успеха (имеется в виду, иметь пользователей). - person John Zwinck; 16.02.2018
comment
@JohnZwinck: я могу представить, что вы могли бы отладить на std::array. Например, отладочная версия стандартной библиотеки может добавить канареечное поле до и после массива, содержащегося в std::array, и протестировать их в каждом методе для обнаружения записи за пределами границ. Это вполне правдоподобно. Это не сломает действительные программы, но сломает программы с этим reinterpret_cast. - person michalsrb; 16.02.2018
comment
@michalsrb: это сломает действительные программы, потому что люди используют std::array как элемент сетевых сообщений и других вещей. На практике то, что вы предлагаете, выглядит неправдоподобно из-за того, как люди используют массивы (C и C++). - person John Zwinck; 16.02.2018