[ROOT] private TCollection copy ctor?

From: George Heintzelman (gah@bnl.gov)
Date: Wed Aug 30 2000 - 23:12:12 MEST


Rooters,

I was just trying to write a nice filtered collection template:

template <class T, class Collection=TOrdCollection>
Collection FilteredList(const TCollection &l) {
  Collection mylist;  // Maybe should specialize with a preset capacity
	              // for classes which have that facility... 
	              // but that's an optimization for later.
  TIter Next(&l);
  while (TObject *obj=Next()) {
    if (T *filtered_obj = dynamic_cast<T *>(obj)) {
      mylist.Add(filtered_obj);
    }
  }
  return mylist;
}

for use in routines that want to find the best object in a collection 
satisfying certain criteria; and I didn't want to write the code over 
and over in different filtering places. Aha, a template, I thought -- 
and a smart compiler will optimize out the copy constructor of the 
return value (as its allowed to do) in most cases, so I don't feel too 
bad about returning the object itself since I will only construct it 
once, really.

Then I compiled and discovered that TCollection::TCollection(TCollection
 &) is *private* and not implemented, and thus this is true also for 
all its descendants. I understand this idiom as preventing copying 
(even in cases where the constructor could be optimized out) -- but 
why? The comment says 'TCollections are too sensitive', but I don't see 
how -- the collections don't own their contents, you're just copying a 
bunch of pointers. Sure, it might lead to a few inefficiencies if 
people use it incorrectly or without thinking about the copy 
constructors... but that's not a reason to PREVENT the activity, and 
even then with modern computing power the copying of a few, or a few 
hundred, or even a few thousand pointers is of very little impact 
except inside inner loops, where profiling ought to catch these kinds 
of mistakes. Is there something terribly dangerous about copying 
collections that I'm missing?

Obviously, I can't use Clone() -- I certainly don't want to copy ALL 
the contents, just the pointers -- and I don't want to return pointers, 
since I don't want the user to be forced to delete the pointer 
afterwards (despite the fact that a lot of ROOT code works this way, I 
find this idiom odious and to be avoided if at all possible*). So what 
should I do?

N.B. I was trying to do this as a way to go around (in a slightly more 
inefficient way) the problem I mentioned some weekes ago with TIter and 
TIterator, which prevents you from defining TIterator classes not 
connected 1-to-1 with a TCollection class. The combination of not being 
able to do either, and being prevented by local policy from using STL 
containers (which do supply copying) is producing a great deal of 
frustration here.

George Heintzelman
gah@bnl.gov

* And besides, it makes this really nice syntax impossible:

GetBestFrom(FilteredList<TSomeClass>(mylist));

Instead, I have to make a local pointer, pass it, and delete it. Never 
mind exception safety, of course...

GAH



This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:32 MET