Range Based For Loop Over Vector in TTree::Branch

ROOT Version: 6.04.02
Platform: 3.16.0-4-amd64 GNU/Linux
Compiler: gcc version 4.9.2 (Debian 4.9.2-10+deb8u1)

Hello,

I am trying to use a range based for loop over a std::vector stored in a branch in a tree. Here is a minimal example showing my problem:

#include <iostream>

#include "TFile.h"
#include "TTree.h"

void make_tree() {

  TFile* fOut = new TFile("output.root","RECREATE");
  TTree* tOut = new TTree("t","");

  std::vector<double> values;
  tOut->Branch("values", &values);

  values = {0,1,2,3,4};
  tOut->Fill();

  values = {5,6,7,8,9,10,11};
  tOut->Fill();

  tOut->Write();
  fOut->Close();

}

void read_tree() {

  TFile* fIn = new TFile("output.root","READ");
  TTree* tIn = (TTree*) fIn->Get("t");

  std::vector<double>* values;
  tIn->SetBranchAddress("values", &values);

  int nEntries = tIn->GetEntries();
  for (int i=0; i<nEntries; i++) {
    tIn->GetEntry(i);

    tIn->Show(i);

    for (unsigned int i=0; i<values->size(); i++) {
      std::cout << "i = " << i << "\t" << (*values)[i] << std::endl;
    }

    //for (const auto& value : *values) {
    //  std::cout << value << std::endl;
    //}
  }

}

Running this produces the intended output:

root [0] .L make_read_tree.C++g
Info in <TUnixSystem::ACLiC>: creating shared library /user/user_name/root_branch_vector_minimal/./make_read_tree_C.so
root [1] make_tree()
root [2] read_tree()
======> EVENT:0
 values          = (vector<double>*)0x2b64f00
i = 0   0
i = 1   1
i = 2   2
i = 3   3
i = 4   4
======> EVENT:1
 values          = (vector<double>*)0x2b64f00
i = 0   5
i = 1   6
i = 2   7
i = 3   8
i = 4   9
i = 5   10
i = 6   11
root [3] .q

If I uncomment the range based for loop in the code, I get a segmentation fault. I do not understand why because this is valid c++:

#include <vector>
#include <iostream>

int main() {

  std::vector<double>* values = new std::vector<double>{0,1,2,3,4,5};

  for (const auto& value : *values) {
    std::cout << value << std::endl;
  }

}

Aren’t I doing the equivalent thing in my ROOT script? Also, I have a related question. When making a branch of std::vector, have I made the branch safely? That is, when I use a C-style array, I am used to adding a leaflist:

int values[2]  = {0};
tOut->Branch("values", &values, "values[2]/I");

Can I safely store a std::vector in a branch without a leaflist?

Any help would be appreciated!

At least:

std::vector<double> *values = 0;

Thank you! As you suggested, it works after adding:

std::vector<double>* values = nullptr;

Do you know the answer to my other question (can I safely store a vector in a branch without a leaf list / would you recommend doing so)?

You already do it, don’t you:

tOut->Branch("values", &values);

Hi Wile,

When I store a C-style array in a branch, I am used to doing:

int values[2]  = {0};
tOut->Branch("values", &values, "values[2]/I");

where I have specified the branchname (“values”), the address (&values), and the leaflist (“values[2]/I”) (I am using the terminology in Case A of https://root.cern.ch/doc/v612/classTTree.html). When I made the branch for the std::vector, I only included the branchname (“values”) and the address (&values). I did not include a leaftlist for the std::vector. Will this cause any unforeseen problems?

See “Case E” in the TTree class reference.

Thank you very much!

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