Я пытаюсь написать класс "STFT", чтобы выполнить короткое время FT. Он вызывает функции fftw3.h, которые выводят массив double * [2], и я хочу создать массив этих массивов. Поэтому я думал, что следующая функция будет подходящей функцией преобразования (это урезанная версия):
void STFT::Transform(double ***transform) {
//stuff
}
Однако, когда я назвал это
transform[100][100][2]
Я получаю сообщение об ошибке:
error: cannot convert double (*)[100][2]' to 'double***
Оглядываясь по сторонам, я думаю, что нашел решение с использованием шаблонов. Хранение определений функций шаблона C++ в файле.CPP, но у меня возникли проблемы с его реализацией, в основном при определении того, где я указываю индикатор типа "T". Мои обновленные функции:
STFT.hpp
class STFT {
public:
template<int N>
void Transform(double transform[][N][2]);
};
STFT.cpp
using namespace std;
template<int N>
void STFT::Transform(double transform[][N][2]) {
cout << "IT WORKS" << endl;
}
и вызов функции находится в main.cpp:
STFT stft;
double transform[100][100][2];
stft.Transform(transform);
Однако это не работает. Сообщение об ошибке:
undefined reference to 'void STFT::Transform<100>(double (*) [100][2])
Я предполагаю, что проблема заключается в моей наивной реализации шаблонов. Я пробовал несколько разных способов, но я не могу найти решение, если кто-то может помочь, я был бы очень благодарен!
Вы C++
это как C++
, но вы используете хранилище данных C-style (и с ошибкой). поэтому используйте "истинное" решение C++: используйте контейнеры стандартной библиотеки.
Здесь, насколько я понимаю, вам нужна матрица пары значений, поэтому почему бы не использовать, например:
typedef std::pair<double,double> myElements;
typedef std::vector<std::vector<myElements>> myContainer;
myContainer data; // instanciation
....
void STFT::Transform(myContainer& d) {
}
Заполнение элементов можно следующим образом:
for( size_t i=0; i<100; i++ )
{
std::vector<myElements> new_vec;
for( size_t j=0; j<100; j++ )
{
double val1 = ...;
double val2 = ...;
new_vec.push_back( std::make_pair(val1,val2) );
}
data.push_back( new_vec );
}
Если вы заинтересованы в производительности, вы можете перенаправить размер вектора на количество элементов.
Если std::pair
неудобно, вы можете использовать std::array
, у которого есть преимущество в размере времени компиляции:
typedef std::array<double,2> myElements;
Затем вместо доступа с помощью .first
и .second
вы просто выполните:
data.at(i).at(j)[0] = ...;
data.at(i).at(j)[1] = ...;
или, если вы уверены в своих значениях индекса, и вы не хотите проверять границы времени выполнения:
data[i][j][0] = ...;
data[i][j][1] = ...;
У них много решений, но, пожалуйста, забудьте обо всех этих указателях и распределении памяти в старой школе. Я обещаю, что я тоже так программировал, я изменился, и я очень рад, что эти контейнеры существуют, больше часов тратится на отладку сообщений об ошибках во время компиляции или непредвиденных сбоев во время выполнения.
И, нет, если правильно использовать, есть (вряд ли) временные накладные расходы.