Передача трехмерного массива в класс (проблемы с конвертацией)

0

Я пытаюсь написать класс "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])

Я предполагаю, что проблема заключается в моей наивной реализации шаблонов. Я пробовал несколько разных способов, но я не могу найти решение, если кто-то может помочь, я был бы очень благодарен!

  • 3
    double *** и (* double) [] [] не одно и то же.
  • 1
    Вторая ошибка компиляции, которую вы получаете, заключается в том, что вы пытаетесь определить функцию шаблона в файле .cpp.
Показать ещё 5 комментариев
Теги:
class
arrays
templates

1 ответ

3
Лучший ответ

Вы 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] = ...;

У них много решений, но, пожалуйста, забудьте обо всех этих указателях и распределении памяти в старой школе. Я обещаю, что я тоже так программировал, я изменился, и я очень рад, что эти контейнеры существуют, больше часов тратится на отладку сообщений об ошибках во время компиляции или непредвиденных сбоев во время выполнения.

И, нет, если правильно использовать, есть (вряд ли) временные накладные расходы.

  • 0
    +1 за добрый совет: D
  • 0
    Я отказался от использования массивов, твой метод гораздо более стабильный. Спасибо за помощь!
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню