0

I am writing a Qt application for matrix arithmetic . I taken input of 2 3x3 arrays in x1 and y1 if int is selected and in x2 and y2 if float is selected . Have a look at MainWindow.cpp .

MainWindow.cpp

int x1[3][3],y1[3][3];
float x2[3][3],y2[3][3];
matrix<int> m1 ;
matrix<float> m2 ;
void MainWindow::addcheck(){
    typecheck();
    if(ui->intradio->isChecked()){
        int** add1 = m1.add(x1,y1);
        putresult1(add1);
    }
    else if(ui->floatradio->isChecked()){
        int** add2 = m2.add(x2,y2);
        putresult2(add2);
    }
}

I am passing these 2 arrays in add function of the matrix class as shown below .

matrix.h

template <class T>
class matrix
{
public:
    matrix();
    T** subtract(T**&,T**&);
    T** add(T**&,T**&);
    T** multiply(T**&,T**&);
};

matrix.cpp

template <class T>
T** matrix<T>::add(T**& a, T**& b) {
    T c[3][3] ;
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            c[i][j] = a[i][j] + b[i][j] ;
        }
    }
    return c ;
}

However, Im recieving the following error while returning the 2d array to ** . Im unable to decrypt the error . Error:

/Users/sarthakmunshi/prac/mainwindow.cpp:74: error: non-const lvalue reference to type 'int **' cannot bind to a value of unrelated type 'int [3][3]'
        add1 = m1.add(x1,y1);
                      ^~
/Users/sarthakmunshi/prac/matrix.h:10: passing argument to parameter here
    T** add(const T**&,const T**&);
                      ^
saruftw
  • 1,104
  • 2
  • 14
  • 37
  • 1
    why a reference to a pointer-to-pointer `T**&`? – m.s. Apr 22 '15 at 10:39
  • 4
    please don't do this. Use `std::vector>` instead. – The Paramagnetic Croissant Apr 22 '15 at 10:39
  • Is that 3 levels of indirection – Floris Velleman Apr 22 '15 at 10:39
  • i have to use primitive arrays for some reason ! – saruftw Apr 22 '15 at 10:39
  • Double pointer for passing a 2d array !?! – saruftw Apr 22 '15 at 10:40
  • 1
    `std::vector>` is not appropriate to matrices. You don't have the guarantee that all the lines have the same size ! The best way to manage mathematical matrices is to use only one vector of `n x m` values and manage accesses to point the good address (as in blas/lapack) – Caduchon Apr 22 '15 at 10:42
  • Is there a simpler way, I can pass and recieve a 2d array ? – saruftw Apr 22 '15 at 10:43
  • 1
    You are returning a variable 'c' from your 'add' method. You mustn't do it, 'c' is created on stack and when it goes out of scope you can't rely on it. – Rames Apr 22 '15 at 10:43
  • 1
    show how `x1` and `y1` are declared and initialized. then if that compile error is gone, you will get undefined behaviour from returning the local variable `c` in `matrix::add` – Zaiborg Apr 22 '15 at 10:44
  • 3
    Any decent matrix implementation would store the rows sequentially in a one dimensional array of size m*n. Unless the size is static, in which case there is no need for indirection. – eerorika Apr 22 '15 at 10:44
  • @Rames but I'm returning it to ** .?? – saruftw Apr 22 '15 at 10:44
  • 1
    Maybe [this SO question](http://stackoverflow.com/questions/8617683/return-a-2d-array-from-a-function) question can help? –  Apr 22 '15 at 10:45

1 Answers1

3

Regardless of what you may have heard before, arrays are not pointers. A bidimensional array has little to do with a pointer to a pointer, which is your compile issue: there is no way of getting from a 2D array to a pointer-to-pointer.

If your arrays are fixed size, you can change the signature of the functions to require it (and incidentally build, which is good, right?):

?? add(T (&a)[3][3], T (&b)[3][3]);

but you are left with what to return from there... of course the answer is Matrix<T>, right? Adding two matrices returns a matrix, which would indicate that the function you are looking for is more like (as a free function):

template <typename T>
Matrix<T> add(Matrix<T> const & lhs, Matrix<T> const & rhs);

Which, of course can be spelled:

template <typename T>
Matrix<T> operator+(Matrix<T> const & lhs, Matrix<T> const & rhs);

I would recommend that you create a minimal matrix class (google, you can see many reference implementations) or that you use one from an existing library.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • Isn't there a rudimentary way of simply passing a 2d array to a method, calculating and then returning it back to another 2d array ? – saruftw Apr 22 '15 at 10:55
  • @saru95: You can pass an array by reference (or pointer), but the problem would be what to return. Either you return a pointer/reference to one of the arguments (you could have `add` mean `+=` and modify the first argument in place) or you need to create an array... arrays cannot be passed or returned by value in the language, which means that you would need to dynamically allocate and return a pointer complicating lifetime for the users... arrays are not really first class citizens in C or C++ – David Rodríguez - dribeas Apr 22 '15 at 11:00
  • Oh ! are you suggesting i cange `c[3][3]` in my code to dynamically allocated version !? – saruftw Apr 22 '15 at 11:02
  • @saru95: No, I am suggesting **not** to do that. I am suggesting that you make `Matrix` a real matrix (holds data) and work in terms of *Matrix* objects rather than plain arrays. Yes, by dynamically allocating the arrays you can manage to get something that builds and works... and is quite hard to use correctly and easy to use incorrectly; don't go there. – David Rodríguez - dribeas Apr 22 '15 at 11:03