I don’t know why it doesn’t work for you - but for me the code works. Could you provide a full example that one can reproduce? (and please use “preformatted text”, otherwise some parts of your code, e.g. the #
characters, will be lost)
Full compilable example that works for me - some ROOT 6.09/03 version, compiled with g++ -Wall -Wextra treeString.C $(root-config --cflags --libs)
:
#include <string>
#include <TTree.h>
#include <TFile.h>
int main() {
std::string str = "Hello world";
TFile *OutputFile = new TFile("FILE_NAME.root", "RECREATE");
TTree *Tree_Data_Set = new TTree("Data_Set", "Data Set");
Tree_Data_Set->Branch("str", &str);
Tree_Data_Set->Fill();
OutputFile->Write();
delete OutputFile;
}
However, when I open the file and view it in a TBrowser and double-click the str object, I get a Warning/Error even though drawing c_str or size seem to work properly:
Warning in <TStreamerInfo::Build>: reverse_iterator<__gnu_cxx::__normal_iterator<const char*,string> >: base class iterator<random_access_iterator_tag,char,long,const char*,const char&> has no streamer or dictionary it will not be saved
Error in <TClass::BuildRealData>: Inspection for allocator<char> not supported!
Warning in <TStreamerInfo::Build>: allocator<char>: base class __gnu_cxx::new_allocator<char> has no streamer or dictionary it will not be saved
I don’t know if it is supposed to be that way - ROOT experts?
My workarounds:
a) I usually store a C-String instead - always works without any problems unless you have a \0 in your string. So simply do something like:
Char_t cstr[500];
tree->Branch("str", &cstr, "str/C");
(loop) {
strlcpy(cstr, str.c_str(), sizeof(cstr));
tree->Fill();
}
b) maybe wrapping the std::string in a struct and adding a dictionary for your string wrapper struct helps? Even though I think it was only required in ancient Root 5.x versions.
General comments about your C++ style:
-
A loop starting with while ( !indata.eof() )
is correct in Pascal (and dialects like Delphi) but almost always wrong or at least bad style in C++. That is because in C++ the eof-bit is only set after you have tried to read past the end of a stream - the check is simply too early in the head of a while loop where you want to know if the NEXT read would fail. Instead simply try to read until reading fails:
while (indata >> str) {...}
The result of operator>>
(the istream) converts to true iff the operation was successful. So always read a stream using stream >> variable
in the while head. The while body will only be executed while reading was successful. That way you can remove the if (indata.eof()) break;
from the while body as well.
-
About importing namespaces: if you are using using namespace std;
, why do you include the using
declarations for std::ifstream/std::ofstream and std::vector as well?