Skip to main content
gamedev.net
🔒 Locked

Templated Array class design problem

Started by Void Sep 18, 2000 at 2:25 AM 9 replies 550+ views
Original Post
Void
Void
I'm trying to do a template array class that checks for out of bounds indexing . It goes a little something like this
    
template<class T>
class Array
{
	public:
		Array(int size)	{	p_ = new T[size]; size_	= size;	};
		~Array()	{	delete	[]p_;	};

		T&	operator[](const int i)	const;

	private:
		T	*p_;		// the pointer

		int	size_;		// the size of the pointer

};

template<class T>
inline T& Array<T>::operator [](const int i) const
{
	if (i >= size_)
		cout << "Out of bounds " << i << endl;

	return(*(p_+i));
}
    
so I can access Array < float > float_array(5); // create 5 floats float_array[0] = 1.0f; This works well as expected but how would I extend it to be able to handle multiple dimensional arrays? float_array[0][3] = 3; // how to do something like that?? Note: There more operators that should be defined which are not shown) Edited by - Void on 9/18/00 4:45:52 AM
derwiath
derwiath
Hello Void.

I don''t think that it is possible to overload the double ''[]''.
But on possibility would be to overload the () operator on the
array instead. It can take as many parameters as you want so you can use it for any dimension of arrays.

    
template <class T>
class CArray{
public:
//...

T& operator()(int iIndex1, int iIndex2){ // <-- you can use any number of params here...

// Check for legal indexing

return m_pArray[iIndex1][iIndex2];
}
//...

private:
T** m_pArray;
};

void main(){
CArray<int> array(3,3);

array(1,2) = 3;
}



Im using that for my matrix classes , I think they are pretty neat.
Good luck..

/ Derwiath

/ Derwiath
- Have a look at the
Grib
Grib
If you want a fixed number of dimentions, overload the () operator to accept say x and y and index like so
T& operator(int x,int y) {return p_[y*width+x];}
T& at(int x,int y) {
int i= y*width+x;
if(i>=size) throw range_error;
return p_;
}

here at() is checked while () is fast, you could also do
T& operator(int x, int y) {return at(x,y);}

If you want something better look at valarray


Void
Void
quote:
Original post by derwiath
But on possibility would be to overload the () operator on the
array instead. It can take as many parameters as you want so you can use it for any dimension of arrays.



That''s nice but it doesn''t really scale very well.. what happens if I want a 3D array? I would have to define another class with the ***p.

I was hoping for something like maybe defining arrays of arrays (maybe something like a vectors of vectors which I''m not sure if it is possible??)..
null_pointer
null_pointer
For your original class, you might want to put #ifdef DEBUG/#endif around the function that checks for out-of-bounds indices, which should provide a good performance boost in release mode (especially if that is your matrix class! ).

If you want to use two dimensions [][], then just do this:


template &lttypename T>
class Array
{
public:
T* operator [] (int index)
{
return( p_[index] );
}

private:
T** p_;
};

Array&ltfloat> myarray;
myarray[0][3] = 0.10f;
myarray[3][2] = 1.00f;



Of course, that code will just give you access violations because there is no constructor and thus no T** array is created. You could add int template parameters to control the size of the array, and probably use them for some kind of compile-time bounds checking (nice!).

To dynamically construct an array of two dimensions, you do this:


// just for example - these can be read from a file or whatever...
int width = 4;
int height = 4;

// multiply-dimensioned arrays are just arrays of arrays
T** p;
p = new T*[width];

// now that we have an array of pointers, make each pointer an array!
for( int x=0; x < width; x++ )
p[x] = new T[height];



To dynamically delete that same array, you do this:


// delete all the arrays
for( int x=0; x < width; x++ )
delete[] p[x];

// delete the array of pointers
delete[] p;



However, if you use the int template parameters for the array dimensions, this is much easier - you can just create a static multiply-dimensioned array, because int template parameters are treated like const:


template &lttypename T, int width, int height>
class Array
{
T p[width][height];
};



Either a static or dynamic multiply-dimensioned array will work the same with the overloaded [] operator that I posted.

Happy Coding!



- null_pointer
Sabre Multimedia
risingdragon3
risingdragon3
Ok! The dread operator[] problem. I struggled with this a few years back when I didn''t really code anything big, but just coded every now and then.
So. Think about this way.
Heres your (pretty nice, by the way - but standard) vector class.

Vector V(10);
//To access, you did:
V[1]=5;
[\code]
Next. To do:
Vector V(10,10);
And have it scale automatically to:
Vector V(10,10,10);
IS IMPOSSIBLE. Because, an constructor cannot have variable arguments. Unfortunately. I think however the next ANSI C++ standard draft allows it. Just wait ...
But for now to have template classes that must be dimmed (in BASIC like speak) to any dimesions:
[code]
Vector M; //not really a Vector NOW!
M.Redim(3,10,10,10); //redimmed to a 3d matrix, 10 by 10 by 10.
M[5][5][5] = 13901.23; //for example.
[\code]
I can''t tell you exactly how to do it (not enough time, 1 am) but:
hint: think of operator[] to be exactly that: function calls to operator[]:
M.operator[](10).operator[](5) = 1.52; //M[10][5] = 1.52;
think of recursive definitions of vectors, multidimesionally.
Good Luck!


------------------------------
What should I put here? You tell me.
Void
Void
I think I was a bit misunderstood..

I wanted to do a template array class that is able to do multi dimensional arrays, not defining multiple template class for each array class that has a different size (ie 1 class for 1D array, 1 class for 2D array, and so on..)

Is that possible?
null_pointer
null_pointer
Ah...I see. Actually, I haven't been online much in the last few days...

std::vector handles multiple array dimensions just fine:


#include &ltvector>
using std::vector;

int main(int, char*)
{
// A vector of vector is an array of arrays.
vector< vector > myarray(5);

for( int x=0; x < 5; x++ )
myarray[x].reserve(10);

// myarray is now like a 5x10 array

myarray[2][3] = 34702; // works as you'd expect
}



Just make sure you place the spaces between the vector&ltint> and the other vector's brackets, or the compiler will think that you've got a >> operator on the end, and you'll get some errors.




- null_pointer
Sabre Multimedia


Edited by - null_pointer on September 20, 2000 5:32:34 PM
risingdragon3
risingdragon3
Well yeah, STL GOOOOD! (it is ) , but the way STL does it is just how I suggested - multiple levels of the same class, so that operator[] call operator[]''s. Anyways yeah, just use the STL. (its faster anyway!)

------------------------------
What should I put here? You tell me.
Wilka
Wilka
quote:

for( int x=0; x < 5; x++ )
myarray[x].reserve(10);

// myarray is now like a 5x10 array

myarray[2][3] = 34702; // works as you''d expect



That should be "myarray[x].resize(10);", reserve just reserves the memory - it doesn''t put anything in it.

std::vector
Void
Void
Thanks guys..

I found this easier way to initialize a 2D vector

vector< vector< int > > v(3, vector< int >(4) ); a 3x4 vector

The whole reason for this array template class I want to write is because the std vector does not check for invalid bounds access.. sometimes there are times when a fixed size array comes into handy, like a 4x4 matrix.

I guess I can take a look at the std vector implementation and follow from there.

Thanks!..

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.