Как правильно вызвать функцию c, принимающую неконстантные аргументы пользовательских указателей из c ++?
Возьмем в качестве очень распространенного примера функцию fftw_plan_dft_1d
из FFTW3. http://fftw.org/fftw3_doc/Complex-DFTs.html#Complex-DFTs
fftw_plan fftw_plan_dft_1d(int n0,
fftw_complex *in, fftw_complex *out,
int sign, unsigned flags);
(fftw_complex
- это typedef для double[2]
).
Предположим, я хочу применить эту функцию к паре const-правильных контейнеров c ++.
std::vector<std::complex<double>> const In = {...};
std::vector<std::complex<double>> Out(In.size());
Как мне это сделать?
_ Первая итерация, я должен извлечь указатель данных из контейнера,
assert(In.size() == Out.size());
fftw_plan fftw_plan_dft_1d(In.size(),
In.data(), Out.data(), // error const
FFTW_FORWARD, FFTW_ESTIMATE);
_ Вторая итерация
но так как это const, я должен constcast.
Я полагаю, что это единственно возможное решение, если предположить, что причиной C-взаимодействия является то, что у C нет аргументов const.
fftw_plan p = fftw_plan_dft_1d(In.size(),
const_cast<std::complex<double>*>(In.data()), // error std::complex is not convertible to fftw_complex
Out.data(),
FFTW_FORWARD, FFTW_ESTIMATE);
_ Третья итерация
Теперь я должен преобразовать std::complex<double>
в fftw_complex
(double[2]
). К счастью, std::complex<double>
должен иметь ту же раскладку, что и double[2]
.
fftw_plan p = fftw_plan_dft_1d(In.size(),
reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(In.data())), // is this UB?
reinterpret_cast<fftw_complex*>(Out.data()),
FFTW_FORWARD, FFTW_ESTIMATE);
и теперь я параноик, очевидно, reinterpret_cast
всегда UB.
Я не знаю, как использовать std::launder
, но я знаю, что он может сэкономить reinterpret_cast
UB в определенных ситуациях.
fftw_plan p = fftw_plan_dft_1d(In.size(),
std::launder(reinterpret_cast<fftw_complex*>(const_cast<std::complex<double>*>(In.data()))), // needs c++17
std::launder(reinterpret_cast<fftw_complex*>(Out.data())),
FFTW_FORWARD, FFTW_ESTIMATE);
В конце концов, является ли это разумным способом вызова C-функции, которая включает в себя const и реинтерпретацию типов?
Я слишком параноик? или это просто, что вызов C из C ++ всегда формально UB в подобных случаях, и я ничего не могу с этим поделать?