0

I'm trying to write a class 'STFT' to perfom a short time FT. It calls the fftw3.h functions, which output a double*[2] array, and I want to create an array of these arrays. So I thought the following would be a suitable transform function (this is a stripped down version):

void STFT::Transform(double ***transform) {
//stuff
}

However, when I called it with say

transform[100][100][2]

I get the error message:

error: cannot convert double (*)[100][2]' to `double***

After looking around, I think I've found a solution using templates Storing C++ template function definitions in a .CPP file but I'm having trouble implementing it, mainly in figuring out where I put the general type indicator 'T'. My updated functions are:

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;
}

and the function call is in main.cpp:

STFT stft;
double transform[100][100][2];

stft.Transform(transform);

However, this doesn't seem to work. The error message is:

undefined reference to `void STFT::Transform<100>(double (*) [100][2])

I imagine the problem lies in my naive implementation of templates. I've tried multiple different ways but I can't seem to get to a solution, if anyone can assist I'd be super grateful!

Community
  • 1
  • 1
user3023621
  • 103
  • 1
  • 9
  • 3
    double*** and (*double)[][] are not the same thing. – this Jun 13 '14 at 22:11
  • 1
    The second compile error you are getting is because you are trying to define a template function in the .cpp file. – pippin1289 Jun 13 '14 at 22:11
  • @pippin1289, you should add that as an answer. – R Sahu Jun 13 '14 at 22:22
  • self - correct me if I'm wrong, but I thought I was passing a double[][][] into a double[][N][2] parameter? pippin - I deleted the template line but still encountering some troubles. I'll have another go and see if I get anywhere – user3023621 Jun 13 '14 at 22:24
  • @user3023621 while having your go at it, [read this question + answers](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) regarding where to implement template functions. – WhozCraig Jun 13 '14 at 22:38
  • Also read up on [*three star programming*](http://c2.com/cgi/wiki?ThreeStarProgrammer). – juanchopanza Jun 13 '14 at 22:42
  • haha cheers for the link, I'm clearly a threetard – user3023621 Jun 13 '14 at 22:51

1 Answers1

3

You are tagging this as C++, but you are using C-style (and error prone) data storage. so use a "true" c++ solution: use the containers of the standard library.

Here, As far as I understand, you need a matrix of pair of values, so why not use for example:

typedef std::pair<double,double> myElements;
typedef std::vector<std::vector<myElements>> myContainer;
myContainer data; // instanciation
....
void STFT::Transform(myContainer& d) {
}

Populating the elements can be done this way:

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 );
} 

If you are concerned with performance, you can preallocate the size of the vector to the number of elements.

If std::pair isn't comfortable, you can use std::array that has the advantage of having a compile-time size:

 typedef std::array<double,2> myElements;

Then, instead of accessing with .first and .second, you just do:

data.at(i).at(j)[0] = ...;
data.at(i).at(j)[1] = ...;

or, if you are sure about your index values, and you dont want run-time bounds checking:

data[i][j][0] = ...;
data[i][j][1] = ...;

They are plenty of solutions, but please, forget about all these pointers and old-school memory allocation. I promise, I also used to program like this, I changed, and i am so glad that these containers exist, no more hours spend to debug either compile-time error messages , or run-time unexpected crashes.

And, no, if correctly used, there is (hardly) no timing overhead.

kebs
  • 6,387
  • 4
  • 41
  • 70
  • I give up using arrays, yours is a far more stable method. Thanks for the help! – user3023621 Jun 13 '14 at 23:07
  • Trust me, you won't regret using the containers of the standard library. However, be warned that it can take some time to master them in depth... – kebs Jun 13 '14 at 23:11