15,610,426 members
See more:
Hi, i'm just playing around with templates and i'm trying to add two 2D arrays as stated in title...please help how should i change my code to make it work...code shown below...
C++
```template <typename Left, typename Right>
class sum
{
private:
Left *myleft;
Right *myright;
public:
sum(Left *l, Right *r) : myleft(l), myright(r) {}

class Inner
{
private:
Left _myleft;
Right _myright;
public:
Inner(Left l, Right r) : _myleft(l), _myright(r) {}
double operator[](int j)
{
return (_myleft[j]+_myright[j]);
}
};

Inner operator[](int i)
{
return Inner(myleft[i]+myright[i]);
}
};

class array
{
private:
double** data;
int N, M;
public:
array( double **_data, int _N, int _M) :data(_data), N(_N), M(_M) { }

class Proxy
{
private:
double* _data;
public:
Proxy(double* __data) : _data(__data) { }
double operator[](int j)
{
return _data[j];
}
};

template <typename Left,typename Right>
void operator=(sum<Left,Right> expr)
{
for(int i=0; i<N; ++i)
for(int j=0; i<M; ++j)
data[i][j] = expr[i][j];
}

Proxy operator[](int i)
{
return Proxy(data[i]);
}
};

template <typename Left>
sum<Left, array> operator+( Left a, array b)
{
return sum<Left, array>(a,b);
}

int main()
{
double **test;
test = new double*[5];
for(int i=0; i<5; ++i){
test[i] = new double[4];
for(int j=0; j<4; ++j){
test[i][j] = 1.0;
}
}

array a(test,5,4), b(test,5,4), c(test,5,4);

c = sum<array,array>(a,b);  // <<----error here

for(int i=0; i<5; ++i){
cout<<"\n";
for(int j=0; j<4; ++j){
cout<<c[i][j]<<" ";
}
}
}```
Posted

## Solution 3

I would not use pointers to elements but rather define the Matrix using numeric template parameters. E.g.
C++
```template<typename TElem, size_t R, size_t C=R>
class Matrix
{
...
};```
Then define internally to that class some types and the data storage, e.g.
C++
```...
public:
typedef TElem ElementType;
typedef ElementType RowType[C];
typedef RowType MatrixType[R];
private:
MatrixType _matrix;
...```
Followed by some constructors for that class, e.g.
C++
```...
public:
Matrix()
{
for(size_t i = 0; i < R; ++i) for(int j = 0; j < C; ++j) _matrix[i][j] = 0;
}
Matrix(const MatrixType &matrix)
{
for(size_t i = 0; i < R; ++i) for(int j = 0; j < C; ++j) _matrix[i][j] = matrix[i][j];
}
...```
Finally implement the adding and some print facility within that class, e.g.
C++
``` ...
{
for(size_t i = 0; i < R; ++i) for(int j = 0; j < C; ++j) _matrix[i][j] += rhs._matrix[i][j];
return *this;
}

void print(ostream& out, const string& name) const
{
out << "### " << name << " ###" << endl;
for(size_t i = 0; i < R; ++i)
{
for(int j = 0; j < C; ++j)
{
if (j > 0) out << ",";
out << _matrix[i][j];
}
out << endl;
}
}
...
```
Note that I implemented in-place adding, i.e. the matrix gets modified by adding the `rhs` elements to the own elements.

Using:
C++
```typedef Matrix<double,2,3> M23;
M23 a;
M23 b(a);
M23::MatrixType m = {{1,0,0},{0,1,0}};
M23 c(m);
a.print(cout, "a");
b.print(cout, "b");
c.print(cout, "c");
c.print(cout, "c");```

Result:
```### a ###
0,0,0
0,0,0
### b ###
0,0,0
0,0,0
### c ###
1,0,0
0,1,0
### c ###
2,0,0
0,2,0```
Cheers
Andi

v3
Daniel Pfeffer 2-Mar-15 2:46am
The only modification that I would make would be to overload the '+=' and '+' operators to perform the matrix addition.

## Solution 1

You have a few issues, for one the constructor of `sum` takes pointers to `Left` and `Right` but when used, pointers are not being passed.

I think the problem becomes simpler to look at if the internal classes are broken out;
C++
```#include<iostream>

using namespace std;

/* represents a one-dimensional array */
template<typename T> class row {
private:
T* data;
size_t n;
public:
row(T* data, size_t n)
: data(data), n(n) {
}

T operator[](int i) {
return data[i];
}
};

/* represents a two-dimensional array */
template<typename T> class array {
private:
T** data;
size_t n, m;
public:
array(T** data, size_t n, size_t m)
: data(data), n(n), m(m) {
}

row<T> operator[](int i) {
return row<T>(data[i], m);
}
};

/* represents a two rows from two arrays, observable as a single summed row */
template<typename T> class sum_row_proxy {
private:
row<T> left;
row<T> right;
public:
sum_row_proxy(row<T> left, row<T> right)
: left(left), right(right) {
}

T operator[](int i) {
return left[i] + right[i];
}
};

template<typename T> class sum {
private:
array<T> left;
array<T> right;
public:
sum(const array<T>& left, const array<T>& right)
: left(left), right(right) {
}

sum_row_proxy<T> operator[](int i) {
return sum_row_proxy<T>(left[i], right[i]);
}
};

int main() {
double **test = new double*[5];
for(int i = 0; i < 5; ++i) {
test[i] = new double[4];
for(int j = 0; j < 4; ++j) {
test[i][j] = 1.0;
}
}

array<double> array_a(test, 5, 4);
array<double> array_b(test, 5, 4);

sum<double> s(array_a, array_b);

for(int i=0; i<5; ++i){
cout<<"\n";
for(int j=0; j<4; ++j){
cout<<s[i][j]<<" ";
}
}

return 0;
}```

I've tried to use (roughly) the same classes you used, but this problem can also be solved by a single class (plus a proxy class for the second indexer) taking two `T**` as input.

Hope this helps,
Fredrik

## Solution 2

I would not declare a template class, but a template function. And would design the function with three arguments for: left operand, right operand, and result. If you don't use a result argument, you will have to pass the result as the return value of your function. That, however, is not what you want. If the return value would also be a pointer to an array, the function would have to allocate that array. And the calling code would have to free the array.

So: I would go for something like:
```template<typename t="">
void sum2D (T* pLeft, T* pRight, T* pSum, int cols, int rows)
{
int n = cols * rows;
for (int i = 0; i < n; ++i)
pSum[i] = pLeft[i] + pRight[i};
};
</typename>```

Note that now the caller has to allocate the space for the result array.