Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!zephyr.ens.tek.com!uw-beaver!cornell!rochester!kodak!islsun!cok From: cok@islsun.Kodak.COM (David Cok) Newsgroups: comp.lang.c++ Subject: Re: To template or not Message-ID: <1991Jun13.143127.19044@kodak.kodak.com> Date: 13 Jun 91 14:31:27 GMT References: <1991Jun12.193426.8289@lynx.CS.ORST.EDU> Sender: news@kodak.kodak.com Organization: Eastman Kodak Co., Rochester, NY Lines: 109 In article <1991Jun12.193426.8289@lynx.CS.ORST.EDU> budd@fog.cs.orst.edu (Tim Budd) writes: .. details of version of List class with a generic class doing the work and a template which derives from that class to provide type safety. > >Well, this works fine with ONE small exception. In order to test whether >something is already in the container, or remove it from the container, you >need some notion of what it means for two things to match. This is >inheritantly application-specific (assumption c - we can't assume the items >in the container will respond to ANY message, not even an equality test). >In my original design, I achieved this by defining a virtual method >``match(void *, void *)'' which was required to be overridden by >subclasses. With templates I can move this forward epsilon (making the >arguments pointers to the right type), but it is STILL the case that the >operation is inheritantly application specific. It seems to me that the >best way to handle this is STILL to make a new subclass. So even with >templates, you end up subclassing. Right? Not necessarily, the property of two things matching is part of the definition of the things, not of the list of things. To be specific -- and use the example below -- the property of equality of Cards should be a method of Cards, not on CardLists. Thus there would be a method int Card::operator==(Card* b) { return (suit()==b->suit() && rank() == b->rank());} Then the method in CardList would be int CardList::match(void *a, void*b) { return ((Card*)a) == ((Card*)b); } which can easily be put in template form. template list: public genericList { ... virtual int list::match(void* a, void* b) { return ((T*)a) == ((T*) b); } Now the only problem is that one can only make list's (with the template) of classes which have implemented operator== as the equality to use as a match. One could go a step further and supply a parameter which is a pointer to a member function which could be used as the test for equality (that was *could*, not *should*...) So by defining Card with the equality, CardList can be implemented simply as list without needing additional subclassing. > >To illustrate, the example. ``genericList'' is my name for the >void-holding list class. Here is the template'd class. > >template class list : public genericList { >public: > void add(T * ele) > { genericList::addToEnd(ele); } > > T * current() > { return (T *) genericList::current(); } > > int includes(T * ele) > { return genericList::includes(ele); } > > T * remove(T * ele) > { return (T *) genericList::remove(ele); } > > virtual int equal(T *, T *); > >protected: > // match invokes equal - users should now override equal > virtual int match(void *, void *); >}; > >template int list::equal(T * a, T * b) >{ return a == b; } > >template int list::match(void * a, void * b) >{ return equal((T *) a, (T *) b); } > >Now, suppose we want to make a list of cards. Here is what I need to do >if two cards are equal if they have the same rank and suit (even if they >aren't pointer-equivalent). > >class CardList : public list { >public: > virtual int equal(Card *, Card *); >}; > >int CardList::equal(Card * a, Card * b) >{ > return (a->rank() == b->rank()) && (a->suit() == b->suit()); >} > >So the whole point is that yes templates can make SOME things easier and >less error prone, and are therefore probably a GOOD THING (and I will >include them in the next release of my generic classes), but like any tool >they aren't the only solution to all problems. > >--tim budd > >p.s. I've also received a large number of messages of the sort ``it doesn't >compile on xxx'', for which I am grateful, and a few which also said ``and >here is why and how you can fix it'' for which I am even more grateful. >It was also pointed out that ``generic'' might be a bad choice of prefix, >since it means something else on a few C++ systems. David R. Cok Eastman Kodak Company -- Imaging Science Lab cok@Kodak.COM