Using the [] operator overloading on a class.

Started by
28 comments, last by Roof Top Pew Wee 20 years, 9 months ago
quote:Original post by davepermen
uhm.. you don''t like unsigned int?..
No. It makes simple calculations and comparisons more cumbersome when you have to keep in mind that the values can''t get negative.
if (a - b >= 0) //oops, always true
if (a >= b) //a working variant
Thus uint is non-intuivive. The double plus range is useless almost always and the lack of negative values can bite you in the ass. Why should I like it? You tell me.
quote:guess so, operator [] should have one parameter, and that one parameter is of type size_t (at least in the std:: namespace objects)..

guess what size_t is?!?
I know. I never claimed I liked STL''s way of doing it.
Advertisement
You have a point Zipster, but I still fail to see any reason to use exception for programming related problems. The closest thing I could think of is to display it on the debug window, but definitely not to throw an exception.

AP, there are cases where negative sign is unnecessary such as indices, but there are also cases where negative sign is important, like in your example. Obviously, I wouldn''t use signed int for indices, but I would definitely use it for math.
Exceptions are merely a nice way of letting the programmer know of any problems, while at the same time allowing the program to take care of any necessary cleanup. It''s better than just letting the whole program crash and go to shambles, in other words. But even if it is just a message to the debug window, at least you are notified if and possibly when an out-of-bounds occured.
quote:Thus uint is non-intuivive.

Unsigned integers are highly intuitive for array indices. However, I also don't think you should make the parameter for operator[] unsigned because, again, it masks problems. If you happen to pass a negative number, due to some problem in the code, it will happily be interpreted as its positive equivalent, instead of allowing the function to perform a bounds check with the negative number, which will always fail. Most likely it will still be out of bounds after the conversion, since a literal interpretation of the sign bit would result in a huge number, but who knows how big an array you have.

[edited by - Zipster on July 5, 2003 4:24:08 AM]
quote:Original post by guppy
but it does worry me that you have no bounds checking

Why does it worry you? The reason that there is no bounds checking is because most of us are aware of the performance issues. You can just add a method to your class that performs bound checking, or, if you want to go to the extreme, you could derive an additional class. For example, the std::vector class's index operator (operator[]()) doesn't perform bounds checking, but it also has an additional method, at(), which does perform bounds checking. (There is also an overloaded const version of at().)

[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || MSVC++ Library Fixes || BarrysWorld || E-Mail Me ]

[edited by - Lektrix on July 5, 2003 8:00:12 AM]
[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || CUJ || MSVC++ Library Fixes || BarrysWorld || [email=lektrix@barrysworld.com]E-Mail Me[/email] ]
quote:Original post by Roof Top Pew Wee
Well, you prob get what I''m trying to do, but I have no idea how to return a l value. Could someone help me out on that?


--Vic--

The future of 2D game development:
Flat Red Ball


5 = var; //impossible because 5 is a r value only

an l value is a variable assigned a value or another variable.
that is why you want to be returning a reference to an l value like Zipster and Greatwolf suggested.
quote:Original post by davepermen
guess so, operator [] should have one parameter, and that one parameter is of type size_t (at least in the std:: namespace objects)..
...with the exception of map.
EDIT: ...and come to think of it, valarray has some bizarre overloads of operator[].

[edited by - Beer Hunter on July 5, 2003 9:37:32 PM]
Bounds checking are simple to do, and makes your code a lot easier to debug. Just use the assert macro like this:

Type &operator[](unsigned int index) { assert( index < MAX_BOUND ); return mydata[index]; }

and it will halt the code and give an error message if the given index is out of bounds. But only in debugging mode. In release mode, the assert statement will be ignored, so any "customer" won''t have to know about this.
Not very on-topic, but hey... alnite, you seem to be a bit hung up on the idea that an exception/error must be handled where it is generated... quite to the contrary, throwing a chain of exceptions all the way back to the top/user level can be very helpful in determining the reason behind that little "out of bounds" error.

Its not much good breaking out at that low level... so the index was out of bounds... what does that tell you? Not much, so we throw an exception back to the caller (logging as we go), which may throw again to its caller if cannot recover, and so on up the call stack, thus giving us a frame of reference which can tell us the circumstances of the error (which should point to the cause).

I have to agree with Zipster and say that simply hiding the effects of errors is really scary... giving your clients the illusion of stability and correctness is not a very good defense when they come back frothing at the mouth that all their data is corrupted or inaccurate.
Personally, I would use exceptions:
template <class cType>class dArray{public:    ...    cType& operator[]( std::size_t n )    {        return arrayVariable[n];    }    const cType& operator[]( std::size_t n ) const    {        return arrayVariable[n];    }    cType& ss_check( std::size_t n );    const cType& ss_check( std::size_t n ) const;    ...private:    cType arrayVariable[1024];    ...}; template <class cType>cType& dArray<cType>::ss_check( std::size_t n ){    if ( n >= size() )    // size() == 1024 in this case        throw ( CException("Subscript operator - index out of bounds", *this) );  // or whatever exception    return (*this)[n];  // or '' return arrayVariable[n] ''} template <class cType>const cType& dArray<cType>::ss_check( std::size_t n ) const{    if ( n >= size() )        throw ( CException("Subscript operator - index out of bounds", *this) );    return (*this)[n];}


[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || MSVC++ Library Fixes || BarrysWorld || E-Mail Me ]
[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || CUJ || MSVC++ Library Fixes || BarrysWorld || [email=lektrix@barrysworld.com]E-Mail Me[/email] ]

This topic is closed to new replies.

Advertisement