Hi Rooters, It seems right now very difficult to implement a 'private class' idiom in ROOT I/O. The basic idea is encapsulation, and is referred to by some as the 'Pimpl' idiom; it's much in favor in programming circles. Here's what you do to get this: // header file class X { private: class Impl; // declared but not defined. Impl * pImpl; // method declarations -- not definitions. } // Implementation file class X::Impl { // Define the Implementation class. } void X::SomeMethod() { return pImpl->SomeMethod(); } You don't have to go whole-hog on this kind of idiom for it to be useful. For example, you may want to encapsulate the structure of a particular data structure, if that structure is only referred to in the privacy of the internal definitions, but leave some things in the header which need to be referred to quickly in inline functions. Naturally, using the idiom can have its efficiency prices; but assume you are willing to pay those prices for what you dealing with. Now, the problem is that, as far as I can tell, in order to successfully stream the implementation objects in this idiom, they have to be declared and visible to CINT, even if they derive from TObject and I define my own Streamer (obviously I can't have CINT generate it if it doesn't know about it, that doesn't bother me). Looking into the guts of ROOT, it looks like the fundamental reason for this is just one: ReadObject needs to be able to call the TClass::New for the class, and TClass::New gets its info from CINT (only). This can get particularly annoying for template classes which you have to link into CINT even though the command line user has no need whatever to know about them. So what I would propose is that there be a way to register a non-CINT-calling functor object for TClass:New(), using the CINT ClassInfo::New() by default but letting the user override it. (If I were writing ROOT I/O from scratch, this is what I would require to register a class with the I/O system.) This mechanism could also be used to minimize CINT-parsing needed in some cases. It would have the side advantage as well of allowing a user to not create a public default constructor for a streamed object, if they tell ROOT instead how to create the 'blank' object it needs to call the Streamer on. Finally, it would allow you to pull off some currently impossible dirty tricks like changing a persistent class's name -- you define just an empty class of the old name, and in its TClass:New functor create instead an object with the new class's name (being careful with version numbering, of course). With proper defaults getting set up, this would be entirely transparent and backwards compatible. So, what do you guys say about doing this? George Heintzelman gah@bnl.gov
This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:36 MET