George A. Heintzelman writes:
>
> Be aware that CINT does not really support template members, so much of
> your template machinery will have to be hidden from CINT in order for
> it to work at the command line. (Either that or you'll have to talk to
> Masaharu Goto personally to figure out how to implement what you need.
> ;)
Yes, I have learned that templates from CINT are tricky. I
anticipated having to put lines like:
#pragma link C++ class RegistryItemXxx<int>;
#pragma link C++ class RegistryItemXxx<double>;
#pragma link C++ class RegistryItemXxx<TObject>;
in my LinkDef.h file in order to let CINT know about the
specializations that will be needed.
Although, the main use of this container is in pre-compiled code.
> Basically, you need to figure out what interface you want to use to the
> ROOT streamers for the registry items. Personally, I would probably do
> it something like this:
>
> In Registry::Streamer, loop over the map writing out the key (either as
> a root TString or with your own TBuffer & operator<<(const std::string
> &) ), the value type (from a virtual RegistryItem function call). and
> the value. The value you write out with a virtual function call in
> RegistryItem, which you will have to specialize for types which are not
> ROOT TObjects.
>
> The tricky part will be deciding how to tell the write out what
> absolute type it is. Unfortunately, you can't portably use the
> type_info::name() function since it is implementation-defined, which is
Life would be a whole lot easier if type_info::name()
was guaranteed to be same on all compilers. This just seem too
useful, does any one know why this was not put in the C++ standard?
One way to solve this problem would be to write a compiler specific
wrapper function to reformat the output of type_info::name() into some
canonical format. This was done in the implementation used for:
http://www.mathcs.sjsu.edu/faculty/pearce/patterns.html.
He used djgpp and VC++ which aparently had relatively simple class
name encodings. I have looked at what kind of names G++ produces, and
they are in general not so simple.
> precisely why the ROOT guys use their ClassName() and such the way they
> do. If you want to write out ROOT objects, you're set -- just use the
> class's ClassName function. For other classes, you probably ought to
> write a specialization of RegistryItemXxx<T>::Name. For read in, you
> supply a registry of RegistryItemXxx<T>::Name which can look up a
> static function returning a T* for the relevant classname string.
Thank you for this good advice, I think I even understand it.
As for handling non-ROOT types, I guess I can safely restrict all
non-TObject types to only the few basic C++ types (int, double, etc)
and hand code specialized constructors which instead of saving the raw
value to fData, first wraps the raw value in a TObject based class.
There is still the issue of catching the error when someone tries to
pass a non-base or TObject derived type.
> You DO realize you're basically redoing ROOT-io in the way it would
> probably have been done had the ROOT guys been able to portably use
> template machinery when they first wrote it, right?
<gulp> That is sobering. Am I doing a good thing or a foolish thing?
> > // The container
> > class Registry
> > {
> > public:
> > // non-templated ctor/dtor
> >
> > // templated accessors
> > template<class T> T GetVal(string key);
> > template<class T> void SetVal(string key, T value);
>
> This of course should be SetVal(string key, const T & value), right?
> You don't want to make more copies than you must (and you must make one
> when you create your RegistryItemXXX).
Oops, yes, it should be (but wasn't). And yes, I do ``new'' a copy
for storing in the RegistryItemXxx<T>. Thanks.
-Brett.
This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:35 MET