Double_t in a TList


I whish to know if it was possible to add many variables declared as Double_t in a TList ?

c:\Documents and Settings\alice\Mes documents\Visual Studio Projects\BenchTest\BenchTest\Channel.cpp(286) : error C2440: ‘cast de type’ : impossible de convertir de ‘TObject *’ en 'double’
Aucun contexte dans lequel cette conversion est possible


Only objects derived from TObject can be added to a TList.
To add an array of Double_t use a TVectorD object.


Thanks Rene,

I had never used the “TVectorD”, another aspect which I discover. and a powerfull solution !!!

Best Regards

Hi there,

TVectorD (TVectorT in the reference guide) is limited to 5 elements.
I’m trying to find a way to work with a linked list of doubles in CINT.
I’ve come up with this

TList *mylist = new TList() ; for (Int_t i=0 ; i<10 ; i++) { mylist->Add(new TParameter<double>(TString::Format("x%02d",i),i*1.)) ; } for (Int_t i=0 ; i<mylist->Capacity() ; i++) { printf("\n%f",((TParameter<double>*)(mylist->At(i)))->GetVal()) ; }There should be an easier way though.


TVectorD can contain as many elements as you wish.
When the vector has 5 or less elements, they are kept internally
on the stack , otherwise on the heap. But that should be of
no concern to the user.


Thanks for the correction.
So here comes my stupid question: How do you fill a TVectorD?
I didn’t manage to find any Add()-like method (like in TList or any linked list class).

TVectorD is part of the linear algebra classes and not a container,
so no Add() functions or iterators.
Filling is described in

So this is not a linked list.
Then my question still lies.
Is there any easier way than that proposed above to implement a linked list of doubles working in CINT?


Simply use:root [0] #include <list> root [1] list<double> list; root [2] list.push_back(1.0);Cheers,

Thanks Philippe.
So there must have been some (nice) improvements in CINT.
I’m pretty sure the following macro did not work in the past:

vector<Double_t> *mylist = new vector<Double_t> ; mylist->push_back(1.); mylist->push_back(3.); for (Int_t i=0 ; i<mylist->size() ; i++) { printf ("\n%f",mylist->at(i)) ; }It does now. So much the better! :slight_smile:

On the contrary, the result is more mitigated with TObjects: :cry:

Double_t x[3] = {1.,2.,3.} ; Double_t y[3] = {1.,2.,3.} ; vector<TGraph*> *mylist = new vector<TGraph*> ; mylist->push_back(new TGraph (3,x,y)); mylist->push_back(new TGraph (3,x,y)); printf ("\n%f\n",mylist->at(1)->GetX()[2]) ; /// DOES work in CINT for (Int_t i=0 ; i<mylist->size() ; i++) { printf ("\n%f",mylist->at(i)->GetX()[0]) ; } /// DOES NOT work in CINT (works fine with ACLIC)This could be overcome using TList at the expense of very irritating necessary “cast wrapping”:

Double_t x[3] = {1.,2.,3.} ; Double_t y[3] = {1.,2.,3.} ; TList *mylist = new TList() ; mylist->Add(new TGraph (3,x,y)); mylist->Add(new TGraph (3,x,y)); printf ("\n%f\n",((TGraph*)(mylist->At(1)))->GetX()[2]) ; for (Int_t i=0 ; i<mylist->GetSize() ; i++) { printf ("\n%f",((TGraph*)(mylist->At(i)))->GetX()[2]) ; }Unless anyone has a nice hint to share… [-o<



To properly use an STL container you need (in most case) to generate a dictionary for int. For list the dictionary is provided with the ROOT build (and its loading is triggered by the #include). For the STL instances we do not provide a dictionary for (for example vector<TGraph*>) you need to generate it your self with is as simple as writing this small file:// loader.C #include <vector> #include "TGraph.h" #ifdef __MAKECINT__ #pragma link C++ class vector<TGraph*>+; #endifand load it into your via ACLiC:root [] .L loader.C+


Thank you so much Philippe.

Hi Philippe,
Is there any way to cope with such templates:

[code]#include <TROOT.h>
#include <TClass.h>
#include <TH1.h>
#include <TH2.h>

// #pragma link C++ ?

void MRF_binarizeHisto ( ATH* histo )
TString type = TString(histo->Class()->GetName()) ;
if ( ! (type.Contains(“TH1”) || type.Contains(“TH2”) ) ) { fprintf (stderr,"\n\n!!!ERROR in <MRF_binarizeHisto>: bad type!!!\n\n") ; getchar() ; exit(1) ; }
if ( type.Contains(“TH1”) ) { for (Int_t ibin=1 ; ibin<=histo->GetNbinsX(); ibin++) { if ( TMath::Abs(histo->GetBinContent(ibin)) > 0 ) { histo->SetBinContent(ibin,1) ; } } }
else if ( type.Contains(“TH2”) ) { for (Int_t col=1; col<=histo->GetNbinsX(); col++) { for (Int_t row=1; row<=histo->GetNbinsY(); row++) { if ( TMath::Abs(histo->GetBinContent(col,row)) > 0 ) { histo->SetBinContent(col,row,1) ; } } } }
return ;
}[/code]I’ve tried several #pragma statements in vain.


As you have it (and thanks to the class hierarchy of the ROOT histograms) you functions does not need to be templated at all! You can simply use:

template void MRF_binarizeHisto ( ATH* histo );
// Both those syntax should work.
#pragma link C++ function MRF_binarizeHisto(TH1F*);
#pragma link C++ function MRF_binarizeHisto;


Thanks Philippe.

[quote]Your function does not need to be templated at all![/quote]True only if histo->Class()->GetName() is replaced byhisto->GetClassName()That’s a pity I’d missed that point so far!

[quote]// Both those syntax should work.[/quote]I’d tried the second one actually.
None of them works unfortunatelly :frowning:

histo->ClassName() NOT histo->GetClassName()I’m sorry :blush:

Actually you meant:TString type( histo->IsA()->GetName() );and you can even do if ( ! histo->InheritsFrom( TH1::Class() ) ) { fprintf (stderr,"\n\n!!!ERROR in <MRF_binarizeHisto>: bad type!!!\n\n") ; getchar() ; exit(1) ; } if ( histo->InheritsFrom( TH2::Class() ) ) { // 2D histogram stuff } else { // 1D histogram stuff }


Thx Philippe.
Any clue for the #pragma thing?


With#ifdef __MAKECINT__ #pragma link C++ function _MRF_binarizeHisto_(TH1*); #endif

I get the correct dictionary:

root [0] .L tt.C+ Info in <TUnixSystem::ACLiC>: creating shared library /private/var/tmp/./ root [1] .function > res01 root [2] .! grep MRF res01 -1:-1 0 public: void _MRF_binarizeHisto_(TH1* histo);


Thanks Philippe.
Indeed you get the correct dictionary if the prototype of the function is declared before the #pragma block.
Attached’s a complete working example using the template way (mrf_template.C) and the “plain/smart” way (mrf.C). Just type .x ztest.cpp[+]As the function call in ztest.cpp has to be the same in both cases* (namely MRF_binarizeHisto()), there’s no point in implementing the template case indeed.

  • Using MRF_binarizeHisto() does not work in CINT (which is normal considering the pragma statement used)
  • MRF_binarizeHisto() (without any <>) does not make ACLIC whinge
    ztest.cpp (656 Bytes)
    mrf_template.C (864 Bytes)
    mrf.C (686 Bytes)