[ROOT] ostream << on template class (and related things)

From: Christoph Borgmeier (borg@ifh.de)
Date: Fri Jan 12 2001 - 21:28:01 MET


Hello,

I just managed to put some of my very old problems into a small
demonstration program (ROOT 3.01). I would be very glad, if I got
answers or comments on as many of them as possible. The problems are
marked with `***' below.

I tried to use a compiled operator<<(ostream,A<T>) in ROOT's interactive
mode. It was not obvious to me whether there is a suitable LinkDef
entry.

Here is an example:
------------------------------- A.h ------------------------------
#include <iostream>

template <class T>
class A
{
public:
 void print(std::ostream& os) const { os << '(' << T(65) << ')'; }
};

template <class T>
std::ostream& operator<<(std::ostream& os, const A<T>& a)
{
  a.print(os);
  return os;
}
-------------------------------------------------------------------

(LinkDef.h contains
  #pragma link C++ class A<int>;
  #pragma link C++ class A<char>;
)

*** The only way I found to ask rootcint to create the dictionary for
operator<< was to add a superfluous friend declaration:

----- in A.h inside template<class T> class A ---------------------
  friend std::ostream& operator<<
#ifndef __CINT__
  <>
#endif
  (std::ostream&, const A<T>&);
-------------------------------------------------------------------

*** [Reason for #ifdef __CINT__: the correct <> version lets rootcint
create invalid code.]

With this hack(?), the operators are created correctly.

But both of my recent projects had declarations which caused rootcint to
instantiate the templates too early (i.e. before reading LinkDef.h?): If
I add

-----in A.h after template<class T> class A {...};-----------------
A<int> dummy();
-------------------------------------------------------------------

CINT forgets to create the code for operator<<(ostream&,A<int>). This is
obviously due to the `instant' instantiation on reading the declaration
of dummy (visible with the trace option).

*** Is there a way to influence CINT's behaviour? My real project
suffers even more because some return values, parameters, or pointers
which cause the instantiation, can only work on forward declarations
(leads to cyclic dependencies of CINT's template instantiations).

Thanks your patience and in advance for any comment,
Christoph


P.S. A.h and LinkDef.h are attached to this message. The rootcint call
is 
rootcint -f out.cxx -c -T A.h LinkDef.h


-- 
 Christoph Borgmeier <borg@ifh.de>
 Address: Humboldt University, Institute for Physics
          Invalidenstr. 110, D-10115 Berlin, Germany
 Phone: +49(30)2093 7816       Fax: +49(30)2093 7642

#include <iostream>

template <class T>
class A
{
public:
  friend std::ostream& operator<<
#ifndef __CINT__
  <>
#endif
  (std::ostream&, const A<T>&);

  void print(std::ostream& os) const { os << '(' << T(65) << ')'; }
};

A<T> GetX();

template <class T>
std::ostream& operator<<(std::ostream& os, const A<T>& a)
{
  a.print(os);
  return os;
}


#ifdef __CINT__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ class A<int>;
#pragma link C++ class A<char>;

#endif



This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:50:33 MET