|
Boost : |
From: Fernando Cacciola (fcacciola_at_[hidden])
Date: 2001-05-11 12:20:43
Bill Seymour wrote:
> >
> > OPINION: All the non-assignment operations should be functions,
> > NOT members. NEVER use members for functional operations.
> >
>
> I note that Fernando Cacciola agrees. What's the reason?
>
It's actually a matter of personal philosophy. I'll try to explain it:
Consider the relation between a class and the operations (or methods) it
supports.
IMO, there are operations that make sense only in the context of the
*particular* class and there are methods that make sense in the context of
the *class's general category*.
Although the meaning of 'class general category' is not well defined, you'll
get what I mean with the following examples:
vector, list, set, my_fancy_container are *containers*.
int,double,rational<>,decimal<> are *numbers*
point,segment,spline,polyhedra are *geometric entities*
Certainly, those categorizations are rather diffuse, but they exist and are
conceptually used when any system is designed.
Now consider the following operations:
) For containers: sort, copy
) For numbers: lexically compare (<,==,>), arithmetically operate (+-*/)
) For geometric objects: transform, draw
It is clear to me that the above operations are conceptually independent of
the particular type; that is, chances are that I write
sort(v.begin(),v.end())
if ( a < b) ...
c = div(a,b)
transform(obj), draw(obj)
thinking not about the particular classes chosen to represent the objects
but the *categories* of those objects.
Now, I know that the classification of a given operation as class-specific
or category-specific can be very ambiguous, except for the trivial cases,
but I think we should try to apply this to decimal<> because of a practical
reason I'll explain below.
I claim that every non-class-specific operation must be implemented as a
non-member (possibly friend) function. The reason should be fairly obvious:
since the operation is not class specific you can change the type of a given
variable without breaking code.
That is,
just as I can write: double a =1 , b= 2, c = a * b ; and then just change
'double' for 'float';
or vector<int> v ; ... ; sort(v.begin(),v.end()) ; and then just change
vector<int> with list<int>;
users of a user defined number class should be able to write code using
number-related-operations such as:
b=abs(a),
q =div(a,b).quot
and then just change money<2> with some_other_type<2>.
Notice that even if some_other_type doesn't come with a proper 'abs' or
'div' function I can always add one without changing some_other_type. I
couldn't do this if I wrote:
b = a.abs()
q = a.div(b).quot ;
OK. I know that the proposed interface supplies non-member forms of the
above, but I would actually take the member-forms away.
I would do the same with 'to_double'.
Conclusion:
I am a numerical algorithms developer, and I designed and used lots of user
defined number types over the years. I changed designs too many times.
But I learn that as a user of a custom number type, I find from time to time
a better class and I like to use it.
Whenever I write:
a.to_double(), a.abs(), a.div(b)
instead of
to_double(a), abs(a), div(a,b)
I am limiting the ability to change the type as desired.
I would like the decimal<> interface to propone the non-member form for
non-class-specific operations.
Fernando Cacciola
Sierra s.r.l.
fcacciola_at_[hidden]
www.gosierra.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk