Hi,
I thought that when I wrote code like:
vector<int> data;
TTree* t = new TTree( "tree", "tree_disc" );
t->Branch( "name", &data );
That I was somehow calling this function:
TBranch* Branch(const char* name, void** obj, Int_t bufsize = 32000, Int_t splitlevel = 99)
since it is the only Branch that can be called with just two parameters (at least according to the info here: http://root.cern.ch/root/html/TTree.html#TTree:Branch%8)
Of course, this has to be wrong, since you cannot implicitly convert vector* to void**. To get to my question, what I would like to know is:
-
what version of TTree::Branch is being called when I use the form tree->Branch( “name”, &data );
-
(probably answered by the answer to question 1) Why do the methods that succeed in the code snippet below succeed, and why do those that fail not succeed? (I know the pointer to void pointer one looks ridiculous and wrong for other reasons.) I did receive the following errors from root:
Error in TTree::Branch: The pointer specified for voidPtr is not of a class or type known to ROOT
Error in TTree::Branch: The pointer specified for doubleVoidPtr is not of a class known to ROOT
- How can a ttree know how to store the actual data of an object just from a pointer? A pointer to an object only tells you the address of the object, right? Are there only specific classes root can deal with? How does it determine the type of the class from the pointer, especially if it is converting it to void*?
Thanks for any help anyone can offer.
–John
#include "TFile.h"
#include "TTree.h"
#include <vector>
using namespace std;
class Example
{
private:
TFile* file;
TTree* tree;
vector<int> dog;
int numFills;
public:
Example(const char* filename)
{
// create a TFile and TTree
file = new TFile( filename, "RECREATE", "member_file" );
tree = new TTree( "member_tree", "member_tree_discription" );
// the number of times to fill the tree
numFills = 100000;
// put some data in our vector;
dog.push_back(1);
dog.push_back(2);
dog.push_back(3);
}
// create branch with branch method.
void thisWorks()
{
tree->Branch("works", &dog);
fillTree();
}
// create branch by passing void ptr to function.
void thisDoesNotWork()
{
createBranchVoidPtr( "voidPtr", &dog );
fillTree();
}
// create branch by passing vector<int>* to function.
void butThisWorks()
{
createBranchTypePtr( "butThisWorks", &dog );
fillTree();
}
// create branch by using template parameter.
void andTheTemplateWorks()
{
createBranchTemplate< vector<int> >("template", &dog );
fillTree();
}
void doubleVoidDoesNotWork()
{
void* dogPtr = (void*)&dog;
createBranchVoidPtr_Ptr("doubleVoidPtr", &dogPtr );
fillTree();
}
// fill the tree.
void fillTree()
{
for( int i = 0; i < numFills; ++i )
{
tree->Fill();
}
}
// void pointer data
void createBranchVoidPtr( const char* name, void* data )
{
tree->Branch( name, data );
}
// typed data
void createBranchTypePtr( const char* name, vector<int>* data )
{
tree->Branch( name, data );
}
// template type data
template <class T>
void createBranchTemplate(const char* name, T* data )
{
tree->Branch( name, data );
}
void createBranchVoidPtr_Ptr(const char* name, void** data )
{
tree->Branch( name, data );
}
// finish up
~Example()
{
tree->Print();
file->Write();
file->Close();
delete file;
}
};
int main(int argc, char** argv)
{
Example e1("worked.root");
e1.thisWorks(); // creates 188K file
Example e2("voidPointerFailed.root");
e2.thisDoesNotWork(); // creates 8K file
Example e3("typePointerWorked.root");
e3.butThisWorks(); // creates 192K file
Example e4("templateWorked.root");
e4.andTheTemplateWorks(); // creates 192K file
Example e5("doubleVoidFail.root");
e5.doubleVoidDoesNotWork(); // creates 8K file
return 0;
}