On Thursday 16 June 2005 19:19, Steven T. Hatton wrote:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1671.pdf
Overloading operator.() & operator.*() ...
We've been doing that for the YaST2 internal libraries for 5+ years (YCPValue and derived classes, YCPValueRep and derived classes). ... I'm confused. Are you saying you used non-standard language features in YaST? How closely did you look at that article? It was proposing a modification to the C++ standard that would permit the overloading of "operator().*", and "operator().". Neither of which are currently overloadable in standard C++.
Uh - sorry, maybe I didn't read the articly you posted thoroughly enough, and
maybe my comments were misleading.
What we did was to overload operator->() and split up our data container
classes into a YCPSomething class and a YCPSomethingRep class.
YCPSomethingRep holds the actual data, while YCPSomething is little more than
a smart pointer - its overloaded operator->() takes care of actually
accessing its corresponding YCPSomethingRep instance.
The basic idea was to avoid null (and otherwise invalid) pointers, yet at the
same time minimize data copying for function calls. etc. - and to do "shallow
copies" whenever possible, since the YCP script language we developed for
YaST2 (initially) was designed as a (somewhat) functional language that
didn't support the notion of references of pointers, so you basically have to
copy around lots of data - in function calls, when returning function results
etc.; but of course you really don't want the interpreter to implement that
by brute-force copying a function's return value - which might be a big
object such as a list or a map where each element in turn can be any kind of
big object. Rather, it does a "shallow copy" of those data, thus incrementing
the reference count in some YCPSomethingRep object, which prevents it from
being freed when the function returns. You get the picture.
Still, that architecture tends to confuse people who are using that on the C++
level: You need a YCPSomething, but you have to be aware that this
YCPSomething is only a ref-counted pointer, so you access almost all (but not
_really_ all, and that's the downside) of its data or functions with
YCPSomething->someFunc(), not, as you would expect it, with
YCPSomething.someFunc(). Still, you have to check it for validity with
YCPSomething.isNull().
OTOH you have to bear in mind that since it already is something like a
reference, it makes little sense to pass it to a function with " const
YCPSomething &" - you pass the real thing, while OTOH in the same function
prototype you really want to use "const std::string &".
Confused? Yes, sure, we, too. ;-)
Maybe it is possible to hide all that confusion if it is designed and
implemented properly, and maybe overloading operator.() and operator*() might
help for that purpose.
But IMHO since you need to keep thinking anyway when using C++ it's a much
better idea not to add yet another layer of abstraction and thus complexity
and remain honest with your C++ programmers: Make it absolutely clear what is
an object and what is a pointer. Don't add to the confusion. It only adds to
the burden they have to carry.
CU
--
Stefan Hundhammer