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!