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