Compiling VERY BASIC template class within a namespace

Dear ROOT-ers,

I have a very simple example of using a template class defined/implemented within a namespace. The header compiles and works just fine as a simple C++ program. When I try to compile the subject code with ROOT, I am having a trouble. I think a problem is due to a lack of my knowledge regarding CINT, thus posting a question here.

Only changes from a pure C++ version of my code into to-be-compiled-with-ROOT version of my code are (1) adding a ClassDefT(ClassName,ClassVersionID) and (2) #pragma for template classes used in a namespace. The attached codes below include (1) in Test.hh and (2) in LinkDef.h.

// Contents of LinkDef.h
#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ namespace TEST;
#pragma link C++ class TEST::Container<string>+;
#pragma link C++ class TEST::Container<int>+;
#endif
// Contents of Test.hh
#ifndef TEST_hh
#define TEST_hh
#include <string>
using std::string;
#include <map>
using std::map;

namespace TEST{

 template< class XDataType >
 class Container
 {
 public:
   Container();
   virtual ~Container()
   {}

   const XDataType operator[]( const int& aKey ) //const
   {
     typename MapType::const_iterator MapTypeIt = fMap.find(aKey);
     if( MapTypeIt != fMap.end() )
	{
	  return MapTypeIt->second;
	}
     return XDataType();
   }
   void Insert( const int& aKey, const XDataType& aDatum )
   {
     typename MapType::value_type aValue( aKey, aDatum );
     fMap.insert( aValue );
     return;
   }

 private:    
   typedef map< int, XDataType > MapType;
   MapType fMap;

   ClassDefT(Container<XDataType>,0)
 };

 enum PrefixKeys
   {
     kOne,
     kTwo,
     kThree
   };

 template<> Container<string>::Container()
 {
   Insert(kThree,"three!");
   Insert(kOne,"one!");
   Insert(kTwo,"two!");
 }
 static const Container<string> kPrefix;

 template<> Container<int>::Container()
 {
   Insert(kOne,1);
   Insert(kTwo,2);
   Insert(kThree,3);
 }
 static const Container<int> kIntegers;

 // orz orz orz
};

#endif

I did:

rootcint -f TestCint.cc -c Test.hh LinkDef.h

which created TestCint.cc and TestCint.h.

g++ -pthread -m64 -I$ROOTSYS/include -c TestCint.cc

Then I get an error:

TestCint.cc: In function ‘int G__TestCint_383_0_16(G__value*, const char*, G__param*, int)’:
TestCint.cc:644: error: invalid use of ‘class TEST::Container<std::basic_string<char, std::char_traits, std::allocator > >’
TestCint.cc: In function ‘int G__TestCint_391_0_16(G__value*, const char*, G__param*, int)’:
TestCint.cc:827: error: invalid use of ‘class TEST::Container’

Would someone help me to find a simple mistake I making in here?

Hi,

The fragment of code you shown looks fine by themselves, the problem is likely somewhere else. What is the code at line 644 of the file TestCint.cc ?

Philippe.

Dear Philippe,

Thank you for your reply.

Actually, when I tried to reproduce the error this morning, the error message is the following (it’s same but referred to a different line #):

TestCint.cc: In function ‘int G__TestCint_383_0_16(G__value*, const char*, G__param*, int)’:
TestCint.cc:527: error: invalid use of ‘class TEST::Container<std::basic_string<char, std::char_traits, std::allocator > >’
TestCint.cc: In function ‘int G__TestCint_391_0_16(G__value*, const char*, G__param*, int)’:
TestCint.cc:710: error: invalid use of ‘class TEST::Container’
kazuhiros-MacBook-Pro:DCTest kazuhiro$ emacs TestCint.cc &

The line# 527 of TestCint.cc is:

G__letint(result7, 105, (long) ((TEST::Container<string>*) G__getstructoffset())->Container());

The line# 710 of TestCint.cc is:

G__letint(result7, 105, (long) ((TEST::Container<int>*) G__getstructoffset())->Container());

By the way, though it might be obvious, I use ROOT 5.26.00 (compiled in 64 bits mode) on my Mac OSX 10.6 with g++ version 4.2.1.

Thank you for your time.

Kazu

Hi,

Technically, the partial specialization of a class template (i.e the specialization of only one of its method)template<> Container<string>::Container() { ... }is not supported by the C++ standard (nonetheless most compilers let’s you get away with it). In practice this confuses CINT (in particular because it is a constructor) thus you need to hide those specialization from CINT:#ifndef __CINT__ template<> Container<string>::Container() { ... } #endif // __CINT__

Cheers,
Philippe.

Dear Philippe,

Thank you very much. After I applied your correction,CINT recognized well and my final goal, which was to import these into python, also worked fine.

Kazu