Hi,
As you noted the streamer automatically created by rootcint is forgetting
to 'clean' the vector before reading the streamer.
For greater flexibility a Streamer should not assume that the object it
is reading is clean and should insure clean-up. (To allow loop like
in the Y::Streamer).
This problem should be fixed shortly in the cvs repository.
Philippe.
> -----Original Message-----
> From: owner-roottalk@pcroot.cern.ch
> [mailto:owner-roottalk@pcroot.cern.ch]On Behalf Of Matevz Tadel
> Sent: Tuesday, August 08, 2000 9:10 AM
> To: roottalk@pcroot.cern.ch
> Subject: [ROOT] streamers for nested stl containers
>
>
> Hi,
>
> Imagine a situation:
>
> X.h <<fnord
> #ifndef _x_h_
> #define _x_h_
>
> #include <TNamed.h>
> #include <vector>
> #include <iostream>
>
> class X : public TNamed {
> public:
> vector<int> mV;
>
> X(const Text_t* n="x") : TNamed(n,0) {}
> void Populate(Int_t M=3) { for(int i=0; i<M; i++) mV.push_back(i); }
> void Spit() {
> cout << GetName() <<": [";
> for(vector<int>::iterator i=mV.begin(); i!=mV.end(); i++) cout
> <<*i<<" ";
> cout <<"]\n";
> }
>
> ClassDef(X,1)
> };
>
> #endif
> fnord
>
> Y.h << fnord
> #ifndef _y_h_
> #define _y_h_
>
> #include "X.h"
> #include <TObject.h>
> #include <vector>
>
> class Y : public TObject {
> public:
> vector<X> mX;
>
> void Populate(Int_t M=3) {
> char a='A', n[2]; for(int i=0; i<M; i++,a++) {
> sprintf(n,"%c",a);
> X x(n); x.Populate(i+1);
> mX.push_back(x);
> }
> }
> void Spit() { for(vector<X>::iterator
> i=mX.begin(); i!=mX.end(); i++) i->Spit(); }
> ClassDef(Y,1)
> };
>
> #endif
> fnord
>
> root session 1:
> root [0] #include <vector>
> root [1] gSystem->Load("libElDictos.so")
> (int)0
> root [2] Y y
> root [3] y.Populate()
> root [4] y.Spit()
> A: [0 ]
> B: [0 1 ]
> C: [0 1 2 ]
> root [5] TFile f("xy.root","RECREATE")
> root [6] y.Write("Y")
> (Int_t)134
> root [7] f.Close()
> root [8] .q
>
> root session 2:
> root [0] #include <vector>
> root [1] gSystem->Load("libElDictos.so")
> (int)0
> root [2] TFile f("xy.root")
> root [3] .ls
> TFile** xy.root
> TFile* xy.root
> KEY: Y Y;1
> root [4] Y.Spit()
> A: [0 ]
> B: [0 0 1 ]
> C: [0 0 1 0 1 2 ]
>
> Conclusion:
> Reading of stl container fails, if its elements contain further stl
> containers ...
> eg:
> // Stream an object of class Y.
> if (R__b.IsReading()) {
> Version_t R__v = R__b.ReadVersion(); if (R__v) { }
> TObject::Streamer(R__b);
> {
> int R__i, R__n;
> X R__t; //!! should be inside loop !!
> R__b >> R__n;
> for (R__i = 0; R__i < R__n; R__i++) {
> R__t.Streamer(R__b);
> mX.push_back(R__t);
> }
> }
> } else { ...
>
> perhaps i live in a dream world, but i would expect the code with
> declaration inside the loop consume the same number of constructors (due
> to optimizations for a variable going out of scope copy constructor for
> stl element is not called). In this case it has to be invoked anyway
> ... we just gain one destruction (which isn't called if my dream
> optimization really exists)
>
> huh ... back to my histograms ...
>
> cheers,
> matevz
>
> --
> ---------------------------------------------------
> Matevz Tadel, E-mail: Matevz.Tadel@ijs.si
> Department of Experimental High Energy Physics F9
> Jozef Stefan Institute, Jamova 39, P.o.Box 3000
> SI-1001 Ljubljana, Slovenia
> Tel.: +386-61-177-3674 Fax: +386-61-125-7074
> ---------------------------------------------------
>
>
This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:31 MET