Linkdef with maps

Hi,

I’m using a ROOT class that contains maps which I’d like to be able to output to file. I know that if the class TMyClass contains e.g.

std::map<Int_t, TObject> var;

then my Linkdef should not only include the class, but also:

#pragma link C++ class std::map<Int_t, TObject>+;

Now, I’d like to use a map like:

std::map<Int_t, std::map<Int_t, TObject> > var;

But now, even with the

#pragma link C++ class std::map<Int_t, std::map<Int_t, TObject>>+;

The code will compile but then, at runtime, I get a warning message like:

Error in TStreamerInfo::Build: The class “TMyClass” is compiled and for its the data member “var”, we do not have a dictionary for the collection “map<Int_t,map<Int_t, TObject> >”, we will not be able to read or write this data member.

Is it just not possible to include a map of maps? Or is there extra information required in the LinkDef?

Cheers,
Matt

Hi Matt,

I put together a minimal example that achieves what you describe. One caveat: the presence of complex data structures is always detrimental for performance and a prime example of such structures is exactly the map of maps.
Said that, let’s come to the exercise:
header

#include <map>
#include "TObject.h"

class dummy : public TObject{
public:
   dummy(){};
private:
   std::map<Int_t, std::map<Int_t, TObject> > m_map;

ClassDef(dummy,1);
};

LinkDef

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

#pragma link C++ class dummy+;
#pragma link C++ class std::map<Int_t, std::map<Int_t, TObject>>+;

#endif

Test

{
gSystem->Load("libclasses.so");
TFile f("outFile.root","RECREATE");
dummy example;
example.Write();
f.Close();
}

Commandlines assuming clang as compiler

rootcint  -f classes_dict.cpp  -c classes.h LinkDef.h ;
clang++ -fPIC -shared -o libclasses.so classes_dict.cpp `root-config --cflags`
root -b -q writeOnFile.C

Cheers,
Danilo

So this works fine for me (although I have issues with clang++ on Mavericks and then issues reading if branched to a Tree rather than written directly to a file). However, the problem persists for my more complex class (which is written to a Tree)…

Hi,

clang was just an example. Gcc can be used as well.
What is the problem? Are you sure the dictionaries are generated correctly and the library is loaded?

Danilo

Yeah, I used gcc to compile in the end. The issue with the tree is that I get an error like:

Error in TTree::SetBranchAddress: The address for “example” should be the address of a pointer!

if I store the variable to a tree rather than just saving the object directly to a file.

For the more complicated class, I tried including all the steps mentioned, but can never write the object to a file if a multi-level map is included (works fine with e.g. map<UInt_t, TObject>, but any map<T, map<T, TObject> > fails).

Hi,

while the ttree error is rather expressive and already points to the fix necessary in your code, feel free to post a reproducer for the second issue if you think this is a ROOT problem.

Cheers,
Danilo