Overloading a matrix constructor for 1 and 2 dimensional arrays.
Hiya, I want to be able to construct my class from either a 1D or 2D array but I don't know how to overload the constructors according to how many dimensions the array has.
I get the feeling that it might not be possible exactly, but I hope someone knows a way to achieve the same or a similar effect. I couldn't find anything specific about this on the web or in the books I have.
Here's a roughish example of what I'm trying to do:
eg
class matrix4
{
public:
matrix4( float * 1DArray );
matrix4( float * 2DArray );
private:
float elements[4][4];
}
matrix4::matrix4( 1DArray )
{
for( int i = 0; i < 4; i++)
{
for( int j = 0; j < 4; j++)
{
elements[i][j] = 1DArray[ i*4 + j ];
}
}
}
matrix4::matrix4( 2DArray )
{
for( int i = 0; i < 4; i++)
{
for( int j = 0; j < 4; j++)
{
elements[i][j] = 2DArray[ i ][ j ];
}
}
}
Hope you can help. I'm fairly new to all this. Thanks for looking!
Re: Overloading a matrix constructor for 1 and 2 dimensional arrays.
Before we look at possible solutions, just wanted to highlight a few points:
There were some compilation errors:
1) Parameter or variable names mustn't begin with a number
2) While defining the functions the parameter types must be mentioned not just the parameter names
3) You can't have any function with the same set of parameters and expect it to overload.
Also use code tags while posting code [code_] [/code_] without the underscore
Possible solution (though needs some refinement):
--------------------------------------------------------------
You would like to initialize a 2 dimensional array using a single dimensional or 2 dimensional array. And you expect the compiler to pick the appropriate type of constructor based on the argument type:
see if this is ok,
1) There is a lot of hardcoding in the code so I declared some global variables instead (couldn't think of an alternative)
2) Could get rid of the hardcoding using dynamic arrays, but then I had to change your program completly to do that
3) Would be happy if someone can suggest a better solution especially to get rid of the global variables (am not too fond of it)
Code:
#include <iostream>
using std :: cout;
using std :: endl;
const unsigned int DIMENSION1 = 4;
const unsigned int DIMENSION2 = 4;
class matrix4
{
public:
matrix4(const float D1Array[]);
matrix4(const float D2Array[][DIMENSION2]);
void display() const;
private:
float elements[DIMENSION1][DIMENSION2];
};
int main()
{
float a[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
float b[4][4] = {101, 102, 103, 104,
105, 106, 107, 108,
109, 110, 110, 112,
113, 114, 115, 116};
matrix4 mat1(a);
matrix4 mat2(b);
system("clear");
mat1.display();
mat2.display();
return(0);
}
matrix4 :: matrix4(const float D1Array[])
{
for( int i = 0; i < DIMENSION1; i++)
{
for( int j = 0; j < DIMENSION2; j++)
{
elements[i][j] = D1Array[ i*4 + j ];
}
}
}
matrix4 :: matrix4(const float D2Array[][DIMENSION2])
{
cout << "\nDisplay matrix\n";
for( int i = 0; i < DIMENSION1; i++)
{
for( int j = 0; j < DIMENSION2; j++)
{
elements[i][j] = D2Array[ i ][ j ];
}
}
cout << endl;
}
void matrix4 :: display() const
{
cout << "\nDisplay Elements:\n";
for(int index1 = 0; index1 < DIMENSION1; index1 ++)
{
for(int index2 = 0; index2 < DIMENSION2; index2 ++)
{
cout << elements[index1][index2] << "\t";
}
cout << endl;
}
}
Re: Overloading a matrix constructor for 1 and 2 dimensional arrays.
Thanks a lot that's great. Sorry for the delay replying, I had to install mingw, I'd never actually compiled a C++ program before.
It seems to work exactly as you say and it uses the correct function for the 1D and 2D arrays. So that's great.
I think I might keep mine hard coded though, I know it's quite limited, but that's what I'm aiming for, to keep it as simple as possible.
I'm curious: do you think the overloading would work just as well if the 1D or 2D array passed to the constructor was dynamically allocated? hehe I should really try that out myself, but don't really know how to do dynamic memory : D. Noob!
Anyway, thanks again.
Re: Overloading a matrix constructor for 1 and 2 dimensional arrays.
Just a small suggestion, this is my view since you state you have never compiled a C++ program:
I feel its best to start from the basics (I know it might be a lot of repetition of what you already know), but every language is different from the other, so clear understanding of the fundamentals would help on the long run. Otherwise you might be forced to start building too many rules about programming in C++ without actually knowing why certain things work and certain things don't. This is my view, will leave it to you to decide.
Yeah there are many ways you can deal your requirement:
1) dynamic arrays is an option by which you can eliminate the hard coding with the dimensions of the array "elements". (I am assuming it would always be a 2D array, but of varying dimensions), but still the constructors would need to contain the dimensions of the source array hard coded.
2) passing the starting address of an N dimensional source array (this way one constructor would be sufficient)
3) like the way posted earlier.
May be a combination of 1) and 2) could help you remove hard coding.
Re: Overloading a matrix constructor for 1 and 2 dimensional arrays.
Quote:
Originally Posted by
Muthuveerappan
3) Would be happy if someone can suggest a better solution especially to get rid of the global variables (am not too fond of it)
With respect to exclusively supporting stack-based arrays, sure (untested):
Code:
template< typename T, class Container = std::deque<T> > class Matrix
{
public:
template<std::size_t X> explicit Matrix(const T(& data)[X]) :
m_data(data, data + sizeof data / sizeof *data)
{
}
template<std::size_t Y, std::size_t X> Matrix(const T(& data)[Y][X]) :
m_data(*data, *data + sizeof data / sizeof(T))
{
}
friend std::ostream& operator<<(std::ostream& outputStream, const Matrix& matrix)
{
std::copy(matrix.m_data.begin(), matrix.m_data.end(),
std::ostream_iterator<T> (outputStream, "\t"));
return outputStream;
}
private:
Container m_data;
};
If not, then a more general solution could be provided; for instance:
Code:
template<class InputIterator> Matrix(const InputIterator first, const InputIterator last)
{
assert(first <= last); //Some sort of sanity check. =\
//Can call 'reserve' here...
std::copy(first, last, std::back_inserter(m_data));
}
Re: Overloading a matrix constructor for 1 and 2 dimensional arrays.
Thanks a lot Plasmator, honestly I didn't think that far.
I am not very familiar with STL, but give me sometime, I will try and do a lil homework and understand the deque constructors and then come back.
Thanks once again for the suggestion !
Re: Overloading a matrix constructor for 1 and 2 dimensional arrays.
Didn't read the thread in detail, but what about something like:
Code:
template<typename T,
typename Array1D = std::vector<T>,
typename Array2D = std::vector<Array1D>
>
class Matrix
{
public:
Matrix(const Array1D& input)
: m_data(1, input)
{
}
Matrix(const Array2D& input)
: m_data(input)
{
}
private:
Array2D m_data;
};
int main()
{
const int dataSize = 4;
int data[dataSize] = { 1, 2, 3, 4 };
Matrix<int> foo(std::vector<int>(data, data + dataSize));
int data2[dataSize][dataSize] = {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 },
{ 13, 14, 15, 16 }
};
std::vector<std::vector<int> > temp(dataSize, std::vector<int>(dataSize));
for (int i = 0; i < dataSize; ++i)
temp[i] = std::vector<int>(data2[i], data2[i] + dataSize);
Matrix<int> foo2(temp);
typedef Matrix<int, std::deque<int>, std::deque<std::deque<int> > > DeqIntMatrix;
DeqIntMatrix foo3(std::deque<int>(data, data + dataSize));
// etc
return 0;
}