www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Free functions versus member functions

reply Kevin Bealer <kevinbealer gmail.com> writes:
janderson Wrote:

 Kevin Bealer wrote:
  > Walter Bright Wrote:
  >>
  >> I eventually ran across this article by Scott Meyers 
 http://www.ddj.com/cpp/184401197
  >> which made a lot of sense. It gives some good guidelines to use to 
 make such decisions, and backs it up with reasoning that I find compelling.
  >>
  >> Isn't it funny how we've completed the circle? We went from all free 
 functions in C, to all member functions in C++, and now back to free 
 functions? <g>
  >
  > I like Meyer's point here.  My view is that classes provide the
  > following added value: they let you define a bunch of operations
  > without defining how they specifically will work.
  >
  > The example I think of is what I believe are two mistakes in the C++
  > STL, the first is 'sort'.  I think it "should" be a member function,
  > as vector::sort and list::sort have to be done differently for
  > efficiency reasons.
 
 I've found sort as a non-member function quite useful when I needed to 
 change the code from a std::vector to a standard C array.  A nice thing 
 about non-member functions is they can work with privative types too.

Me too; now that I think about it there is also the nice aspect that you can sort part of an array/list/vector with it.
  > They give us the efficiency by making list::sort a member and vector
  > can be sorted with sort(v.begin(), v.end()).  But I think that's a
  > mistake, since you can't write a good template that calls x.sort()
  > and expect it to do the best thing.
 
 
 I'm not sure what you what you are getting at here.  I don't think a 
 member function list::sort was a good idea.

There is an advantage to it, in that non-member function list needs to copy values but member function list can just switch pointers. This is important for a list of strings if you don't want the strings to be moved, or if you want to keep an iterator to a particular value from before to after the move. I've never tested the difference in speed so I don't know how important this is, but I think sort() can sometimes take advantage of internal features of a class. That said, having both member and non-member seems okay to me (for this case). But speed depends on the type T (as in vector<T>) as well. For some types, list<T>::sort might be faster and for others, vector<T>::sort. I seem to recall testing set<T> versus vector<T>::sort to see which worked faster and finding that one worked faster if T was int, and the other if T was string. (Just one implementation of course.)
  > The other mistake (I think) is in the other direction, which is the
 'extra' members that classes like string and vector have that give them
 personalities. For example, methods like "push_back()" and "rfind()"
 could be implemented externally for both string and vector, and it would
 result in less complexity AND more capability. (Maybe they wanted
 something like Boyer-Moore for string's find() related code?)
  >
  > Kevin
  >
 
 Perhaps these could be external however it would probably restrict 
 optimizations and verifications that can be applied to these (without 
 exposing more of the class then you need too).  However it does seem odd 
 to have find functions in 2 different places and my pet peeve with STL 
 is that it has low discover-ability.
 
 -Joel

I guess what I'm thinking is that find(a.begin(), a.end(), value) could be written, and string::find(...) could also be written. If the most efficient find() is the external one, then string::find() could just use that. If not, it can use an different internal version. My thinking is that users wanting speed can say s.find(...) and users wanting flexibility could say find(x.begin(), x.end(), ...) where x is any type. Maybe there's a nicer way to do this (I guess people use template specializations?) Kevin
Oct 14 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Kevin Bealer wrote:
 I guess what I'm thinking is that find(a.begin(), a.end(), value) could be
written, and string::find(...) could also be written.  If the most efficient
find() is the external one, then string::find() could just use that.  If not,
it can use an different internal version.
 
 My thinking is that users wanting speed can say s.find(...) and users wanting
flexibility could say find(x.begin(), x.end(), ...) where x is any type.  Maybe
there's a nicer way to do this (I guess people use template specializations?)
 
 Kevin
 

Yes, Walter calls it "uniform function call syntax" or somesuch. Basically: s.find(...) and find(s, ...) become equivalent. This means that you can have a global find functions like thus: size_t find(T,U)(T collection, T thing_to_find) { ... } size_t find(T)(ICollection collection, T thing_to_find) { ... } And optimised member functions for particular implementations struct CrazyCollection(T) { size_t find(T thing_to_find) { ... } } And they all get invoked the same way. The user no longer has to care where the function was written, just that it exists. -- Daniel
Oct 14 2007
parent reply "Janice Caron" <caron800 googlemail.com> writes:
On 10/15/07, Daniel Keep <daniel.keep.lists gmail.com> wrote:
 Basically:

   s.find(...)

 and

   find(s, ...)

 become equivalent.

Almost equivalent? Correct me if I'm wrong, but the former is capable of polymorphism while the latter isn't? I think this uniform call syntax idea is /brilliant/, by the way. I'm all in favor it. Just being clear here.
Oct 14 2007
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Janice Caron wrote:
 On 10/15/07, Daniel Keep <daniel.keep.lists gmail.com> wrote:
 Basically:

   s.find(...)

 and

   find(s, ...)

 become equivalent.

Almost equivalent? Correct me if I'm wrong, but the former is capable of polymorphism while the latter isn't? I think this uniform call syntax idea is /brilliant/, by the way. I'm all in favor it. Just being clear here.

Equivalent from the point of view of the person using it. They're *obviously* not equivalent in how they're implemented, where they're kept, or how they're mangled. I just didn't want to do a Raymond Chen and write the long, boring disclaimer where I precisely qualify every thing I said that could potentially be misinterpreted. I really don't have the patience for that. :) -- Daniel
Oct 15 2007