When to use operator[]

D

Darren Grant

Hi,

Is it good style to use overload operator[] for a class which isn't
really a container?

Eg, I have a class BezierPop, which represents a population of Bezier
curves (yes, we're talking Genetic Algorithms here). Should I overload
operator[] so we can use pop[4] to refer to the 4th chromosome in the
population, even though BezierPop certainly isn't a value-like class
or a container itself.

Another example, I have a class Bezier, which represents a Bezier
curve (a type of spline - just a hoopy type of curve). I have a member
function which returns a 2D coordinate as a function of t, which is an
interval of [0,1]. Should I overload operator[] so I can do curve[0.2]
or should I make a member function, eg curve.t(0.2) ?

Thanks,
Darren Grant
 
C

Cy Edmunds

Darren Grant said:
Hi,

Is it good style to use overload operator[] for a class which isn't
really a container?

Eg, I have a class BezierPop, which represents a population of Bezier
curves (yes, we're talking Genetic Algorithms here). Should I overload
operator[] so we can use pop[4] to refer to the 4th chromosome in the
population, even though BezierPop certainly isn't a value-like class
or a container itself.

Operator [] implies array semantics. If such semantics makes sense with your
class, why not? Whether your class is actually implemented internally as a
container really doesn't matter.

But if pop[4] is the 4th chromosome, why not call it chromosome[4]?
Logically pop[4] should be the 4th pop, whatever that means.
Another example, I have a class Bezier, which represents a Bezier
curve (a type of spline - just a hoopy type of curve). I have a member
function which returns a 2D coordinate as a function of t, which is an
interval of [0,1]. Should I overload operator[] so I can do curve[0.2]
or should I make a member function, eg curve.t(0.2) ?

Again, you use operator [] to simulate an array, which you can't do with a
floating point argument.

Although array semantics make no sense here, you could use function
semantics -- operator (). Then you would have curve(0.2) returning a 2D
coordinate. I can't tell if it makes sense for your application or not, but
at least the floating point argument wouldn't present a problem.
 
J

Jeff Schwab

Cy said:
Hi,

Is it good style to use overload operator[] for a class which isn't
really a container?

Eg, I have a class BezierPop, which represents a population of Bezier
curves (yes, we're talking Genetic Algorithms here). Should I overload
operator[] so we can use pop[4] to refer to the 4th chromosome in the
population, even though BezierPop certainly isn't a value-like class
or a container itself.


Operator [] implies array semantics. If such semantics makes sense with your
class, why not? Whether your class is actually implemented internally as a
container really doesn't matter.

I agree completely.
But if pop[4] is the 4th chromosome, why not call it chromosome[4]?
Logically pop[4] should be the 4th pop, whatever that means.

I believe "pop" is short for "population." Using [] in this context is
fine.
Another example, I have a class Bezier, which represents a Bezier
curve (a type of spline - just a hoopy type of curve). I have a member
function which returns a 2D coordinate as a function of t, which is an
interval of [0,1]. Should I overload operator[] so I can do curve[0.2]
or should I make a member function, eg curve.t(0.2) ?


Again, you use operator [] to simulate an array, which you can't do with a
floating point argument.

[] is actually used for plenty of things other than simulating arrays.
std::map is a great example. Just make sure you document the interface
concisely and clearly in comments near wherever you declare the operator
overload.
Although array semantics make no sense here, you could use function
semantics -- operator (). Then you would have curve(0.2) returning a 2D
coordinate. I can't tell if it makes sense for your application or not, but
at least the floating point argument wouldn't present a problem.

I personally reserve the () operator (with arg(s)) to indicate that I'm
looking for a particular behavior, rather than retrieving a datum,
although I do see Cy's point. I suppose a good guideline would be that
if you consider your code to be calculating a (potentially changeable)
value based on its argument, use (), and change the name of the function
to include a verb, e.g. "get_curve_at_time." If the return value
depends only on the value of the argument, and can never change, you
probably should use [], but make the name of the object reflect the fact
it behaves like a collection of values; e.g., "curves" instead of "curve."

Hth,
Jeff
 
E

EventHelix.com

Eg, I have a class BezierPop, which represents a population of Bezier
curves (yes, we're talking Genetic Algorithms here). Should I overload
operator[] so we can use pop[4] to refer to the 4th chromosome in the
population, even though BezierPop certainly isn't a value-like class
or a container itself.

This case is fine for overloading [].
Another example, I have a class Bezier, which represents a Bezier
curve (a type of spline - just a hoopy type of curve). I have a member
function which returns a 2D coordinate as a function of t, which is an
interval of [0,1]. Should I overload operator[] so I can do curve[0.2]
or should I make a member function, eg curve.t(0.2) ?

Not sure if C++ allows operator overloading with non-integer index.

Sandeep
 
V

Victor Bazarov

EventHelix.com said:
Eg, I have a class BezierPop, which represents a population of Bezier
curves (yes, we're talking Genetic Algorithms here). Should I overload
operator[] so we can use pop[4] to refer to the 4th chromosome in the
population, even though BezierPop certainly isn't a value-like class
or a container itself.

This case is fine for overloading [].
Another example, I have a class Bezier, which represents a Bezier
curve (a type of spline - just a hoopy type of curve). I have a member
function which returns a 2D coordinate as a function of t, which is an
interval of [0,1]. Should I overload operator[] so I can do curve[0.2]
or should I make a member function, eg curve.t(0.2) ?

Not sure if C++ allows operator overloading with non-integer index.

Yes, it does. Any type will be fine.

Victor
 
T

Tom Plunket

EventHelix.com said:
Not sure if C++ allows operator overloading with non-integer index.

Consider operator[] for std::map. In this case, you can index on
any type for which operator< is defined. In general, though,
sure, operator[] can take any type, just like any other class
method. :)


-tom!
 
D

Darren Grant

Cy said:
Hi,

Is it good style to use overload operator[] for a class which isn't
really a container?

Eg, I have a class BezierPop, which represents a population of Bezier
curves (yes, we're talking Genetic Algorithms here). Should I overload
operator[] so we can use pop[4] to refer to the 4th chromosome in the
population, even though BezierPop certainly isn't a value-like class
or a container itself.


Operator [] implies array semantics. If such semantics makes sense with
your
class, why not? Whether your class is actually implemented internally as
a
container really doesn't matter.

I agree completely.
But if pop[4] is the 4th chromosome, why not call it chromosome[4]?
Logically pop[4] should be the 4th pop, whatever that means.

I believe "pop" is short for "population." Using [] in this context is
fine.
Another example, I have a class Bezier, which represents a Bezier
curve (a type of spline - just a hoopy type of curve). I have a member
function which returns a 2D coordinate as a function of t, which is an
interval of [0,1]. Should I overload operator[] so I can do curve[0.2]
or should I make a member function, eg curve.t(0.2) ?


Again, you use operator [] to simulate an array, which you can't do with
a
floating point argument.

[] is actually used for plenty of things other than simulating arrays.
std::map is a great example. Just make sure you document the interface
concisely and clearly in comments near wherever you declare the operator
overload.
Although array semantics make no sense here, you could use function
semantics -- operator (). Then you would have curve(0.2) returning a 2D
coordinate. I can't tell if it makes sense for your application or not,
but
at least the floating point argument wouldn't present a problem.

I personally reserve the () operator (with arg(s)) to indicate that I'm
looking for a particular behavior, rather than retrieving a datum,
although I do see Cy's point. I suppose a good guideline would be that
if you consider your code to be calculating a (potentially changeable)
value based on its argument, use (), and change the name of the function
to include a verb, e.g. "get_curve_at_time." If the return value depends
only on the value of the argument, and can never change, you probably
should use [], but make the name of the object reflect the fact it
behaves like a collection of values; e.g., "curves" instead of "curve."

Hth,
Jeff

Cool, thanks for your help, everyone.

Darren
 
D

Derek

Darren Grant said:
Hi,

Is it good style to use overload operator[] for a class which
isn't really a container?

Eg, I have a class BezierPop, which represents a population
of Bezier curves (yes, we're talking Genetic Algorithms
here). Should I overload operator[] so we can use pop[4] to
refer to the 4th chromosome in the population, even though
BezierPop certainly isn't a value-like class or a container
itself.

Another example, I have a class Bezier, which represents
a Bezier curve (a type of spline - just a hoopy type of
curve). I have a member function which returns a 2D coordinate
as a function of t, which is an interval of [0,1]. Should I
overload operator[] so I can do curve[0.2] or should I make a
member function, eg curve.t(0.2) ?

Thanks, Darren Grant

As others have pointed out, there is no harm in using operator[] for a
non-container class, as long as the meaning of the operator is clear.

However, as a matter of *style*, I usually prefer to use descriptive
member functions. A descriptive name usually goes further to document
and express the meaning of the code. Of course only you can decide if
the meaning of operator[] is clear enough in your domain.

Having said that, my personal opinion is that operator[] is fine for
BezierPop, but I would prefer operator() for the Bezier curve itself.
I tend to associate operator[] with indexing discrete elements, while
operator() is used to evaluate functions (or functors). When you
write curve[0.2], you are not indexing a discrete element, but
evaluating a parametric function, which I would write curve(0.2).
Just my personal opinion.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,156
Messages
2,570,878
Members
47,413
Latest member
KeiraLight

Latest Threads

Top