How to add a branch of user defined class

Hello,

I am trying to add a branch of the std vector of object of my user-defined class, it passes the compilation but generates an error as follows:
Error in TTree::Branch: The class requested (vector) for the branch “xBranch” is an instance of an stl collection and does not have a compiled CollectionProxy. Please generate the dictionary for this collection (vector) to avoid to write corrupted data.
How do I tell the ROOT to know my own class X?

#include <TFile.h>
#include <TTree.h>
#include <vector>

// User-defined class
class X {
public:
  int value;

  // Constructor
  X(int val) : value(val) {}
};

void CreateROOTTree() {
  // Create a ROOT file
  TFile file("tree.root", "RECREATE");

  // Create a TTree
  TTree tree("myTree", "Example Tree");

  // Create a vector of X objects
  std::vector<X> xVec;
  xVec.emplace_back(10);
  xVec.emplace_back(20);
  xVec.emplace_back(30);

  // Create a branch with the vector of X objects
  tree.Branch("xBranch", &xVec);

  // Fill the tree (you can do this in a loop for multiple events)
  tree.Fill();

  // Write the tree to the file and close it
  file.Write();
  file.Close();
}

int main() {
  CreateROOTTree();
  return 0;
}

Please read tips for efficient and successful posting and posting code

Please fill also the fields below. Note that root -b -q will tell you this info, and starting from 6.28/06 upwards, you can call .forum bug from the ROOT prompt to pre-populate a topic.

ROOT Version: 6.22/06
Platform: ubuntu 20.04
Compiler: g++


Hi @haolinli,

As the starting point, you may take a look at I/O of custom classes - ROOT. In particular, you will need a #pragma directive in your linkdef file similar to the one below

#pragma link C++ class std::vector<X>+;

Cheers,
J.

Hi, Thanks very much for your reply, I finally work it through following the Danilo’s reply in this thread.

I am able to write a vector of my user defined class into the root file, but now I have new issue of how to read them. The following code does not work:

void ReadROOTTree() {
  
  TFile file("tree.root", "READ");

  TTree* tree = dynamic_cast<TTree*>(file.Get("myTree"));


  std::vector<X> xVecPtr ;

  tree->SetBranchAddress("xBranch", &xVecPtr);

  // Read the first entry of the tree
  tree->GetEntry(0);


  // Close the file
  file.Close();
}

int main() {
  ReadROOTTree();
  return 0;
}

It pass the compilation but give out the error: Error in TTree::SetBranchAddress: The address for “xBranch” should be the address of a pointer!.

Further I have no idea how to use a pointer to access each element in the vector in that branch, otherwise copying the whole vector out would definitely be not efficient. Any suggestion would be appreciated.

Thanks,
Haolin

SetBranchAddress() requires a pointer to a pointer to std::vector<T> instead. Therefore, the correct form is

  std::vector<X> *xVecPtr = nullptr;
  tree->SetBranchAddress("xBranch", &xVecPtr);

I think there should be something similar to this in the forum already.

Cheers,
J.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.