Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:15:27

0001 // @(#)root/cont:$Id$
0002 // Author: Markus Frank  28/10/04. Philippe Canal 02/01/2007
0003 
0004 /*************************************************************************
0005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
0006  * All rights reserved.                                                  *
0007  *                                                                       *
0008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0010  *************************************************************************/
0011 
0012 #ifndef ROOT_TCollectionProxyInfo
0013 #define ROOT_TCollectionProxyInfo
0014 
0015 //////////////////////////////////////////////////////////////////////////
0016 //                                                                      //
0017 //  Small helper to gather the information neede to generate a          //
0018 //  Collection Proxy                                                    //
0019 //
0020 //////////////////////////////////////////////////////////////////////////
0021 
0022 #include "RtypesCore.h"
0023 #include "TError.h"
0024 #include <vector>
0025 #include <forward_list>
0026 #include <typeinfo>
0027 #include <utility>
0028 
0029 #if defined(_WIN32)
0030    #if _MSC_VER<1300
0031       #define TYPENAME
0032       #define R__VCXX6
0033    #else
0034       #define TYPENAME typename
0035    #endif
0036 #else
0037    #define TYPENAME typename
0038 #endif
0039 
0040 class TVirtualCollectionProxy;
0041 
0042 namespace ROOT {
0043 namespace VecOps {
0044 template <typename T>
0045 class RVec;
0046 }
0047 
0048 namespace Internal {
0049 template <typename T> class TStdBitsetHelper {
0050    // This class is intentionally empty, this is scaffolding to allow the equivalent
0051    // of 'template <int N> struct TCollectionProxyInfo::Type<std::bitset<N> >' which
0052    // is not effective in C++ (as of gcc 4.3.3).
0053 };
0054 }
0055 
0056 namespace Detail {
0057 
0058    class TCollectionProxyInfo {
0059       // This class is a place holder for the information needed
0060       // to create the proper Collection Proxy.
0061       // This is similar to Reflex's CollFuncTable.
0062 
0063    public:
0064 
0065       // Same value as TVirtualCollectionProxy.
0066       static const UInt_t fgIteratorArenaSize = 16; // greater than sizeof(void*) + sizeof(UInt_t)
0067 
0068    /** @class ROOT::Detail::TCollectionProxyInfo::IteratorValue
0069     *
0070     * Small helper to encapsulate whether to return the value
0071     * pointed to by the iterator or its address.
0072     *
0073     **/
0074 
0075       template <typename Cont_t, typename value> struct IteratorValue {
0076          static void* get(typename Cont_t::iterator &iter) {
0077             return (void*)&(*iter);
0078          }
0079       };
0080 
0081       template <typename Cont_t, typename value_ptr> struct IteratorValue<Cont_t, value_ptr*> {
0082          static void* get(typename Cont_t::iterator &iter) {
0083             return (void*)(*iter);
0084          }
0085       };
0086 
0087    /** @class ROOT::Detail::TCollectionProxyInfo::Iterators
0088     *
0089     * Small helper to implement the function to create,access and destroy
0090     * iterators.
0091     *
0092     **/
0093 
0094       template <typename Cont_t, bool large = false>
0095       struct Iterators {
0096          typedef Cont_t *PCont_t;
0097          typedef typename Cont_t::iterator iterator;
0098 
0099          static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
0100             PCont_t c = PCont_t(coll);
0101             new (*begin_arena) iterator(c->begin());
0102             new (*end_arena) iterator(c->end());
0103          }
0104          static void* copy(void *dest_arena, const void *source_ptr) {
0105             iterator *source = (iterator *)(source_ptr);
0106             new (dest_arena) iterator(*source);
0107             return dest_arena;
0108          }
0109          static void* next(void *iter_loc, const void *end_loc) {
0110             iterator *end = (iterator *)(end_loc);
0111             iterator *iter = (iterator *)(iter_loc);
0112             if (*iter != *end) {
0113                void *result = IteratorValue<Cont_t, typename Cont_t::value_type>::get(*iter);
0114                ++(*iter);
0115                return result;
0116             }
0117             return nullptr;
0118          }
0119          static void destruct1(void *iter_ptr) {
0120             iterator *start = (iterator *)(iter_ptr);
0121             start->~iterator();
0122          }
0123          static void destruct2(void *begin_ptr, void *end_ptr) {
0124             iterator *start = (iterator *)(begin_ptr);
0125             iterator *end = (iterator *)(end_ptr);
0126             start->~iterator();
0127             end->~iterator();
0128          }
0129       };
0130 
0131       // For Vector we take an extra short cut to avoid derefencing
0132       // the iterator all the time and redefine the 'address' of the
0133       // iterator as the iterator itself.  This requires special handling
0134       // in the looper (see TStreamerInfoAction) but is much faster.
0135       template <typename T> struct Iterators<std::vector<T>, false> {
0136          typedef std::vector<T> Cont_t;
0137          typedef Cont_t *PCont_t;
0138          typedef typename Cont_t::iterator iterator;
0139 
0140          static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
0141             PCont_t c = PCont_t(coll);
0142             if (c->empty()) {
0143                *begin_arena = nullptr;
0144                *end_arena = nullptr;
0145                return;
0146             }
0147             *begin_arena = c->data();
0148             *end_arena = c->data() + c->size(); // We can not dereference the end iterator at all.
0149          }
0150          static void* copy(void *dest, const void *source) {
0151             *(void**)dest = *(void**)(const_cast<void*>(source));
0152             return dest;
0153          }
0154          static void* next(void * /* iter_loc */, const void * /* end_loc */) {
0155             // Should not be used.
0156             // In the case of vector, so that the I/O can perform better,
0157             // the begin_arena and the end_arena are *not* set to the
0158             // address of any iterator rather they are set to the value of
0159             // the beginning (and end) address of the vector's data.
0160             // Hence this routine (which takes the value of fBegin) can
0161             // *not* update where its points to (which in the case of vector
0162             // would require update the value of fBegin).
0163             R__ASSERT(0 && "Intentionally not implemented, do not use.");
0164             return nullptr;
0165          }
0166          static void destruct1(void  * /* iter_ptr */) {
0167             // Nothing to do
0168          }
0169          static void destruct2(void * /* begin_ptr */, void * /* end_ptr */) {
0170             // Nothing to do
0171          }
0172       };
0173 
0174       template <typename Cont_t> struct Iterators<Cont_t, /* large= */ true > {
0175          typedef Cont_t *PCont_t;
0176          typedef typename Cont_t::iterator iterator;
0177 
0178          static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
0179             PCont_t  c = PCont_t(coll);
0180             *begin_arena = new iterator(c->begin());
0181             *end_arena = new iterator(c->end());
0182          }
0183          static void* copy(void * /*dest_arena*/, const void *source_ptr) {
0184             iterator *source = (iterator *)(source_ptr);
0185             void *iter = new iterator(*source);
0186             return iter;
0187          }
0188          static void* next(void *iter_loc, const void *end_loc) {
0189             iterator *end = (iterator *)(end_loc);
0190             iterator *iter = (iterator *)(iter_loc);
0191             if (*iter != *end) {
0192                void *result = IteratorValue<Cont_t, typename Cont_t::value_type>::get(*iter);
0193                ++(*iter);
0194                return result;
0195             }
0196             return nullptr;
0197          }
0198          static void destruct1(void *begin_ptr) {
0199             iterator *start = (iterator *)(begin_ptr);
0200             delete start;
0201          }
0202          static void destruct2(void *begin_ptr, void *end_ptr) {
0203             iterator *start = (iterator *)(begin_ptr);
0204             iterator *end = (iterator *)(end_ptr);
0205             delete start;
0206             delete end;
0207          }
0208       };
0209 
0210   /** @class ROOT::Detail::TCollectionProxyInfo::Environ
0211     *
0212     * Small helper to save proxy environment in the event of
0213     * recursive calls.
0214     *
0215     * @author  M.Frank
0216     * @version 1.0
0217     * @date    10/10/2004
0218     */
0219    struct EnvironBase {
0220    private:
0221       EnvironBase(const EnvironBase&); // Intentionally not implement, copy is not supported
0222       EnvironBase &operator=(const EnvironBase&); // Intentionally not implement, copy is not supported
0223    public:
0224       EnvironBase() : fIdx(0), fSize(0), fObject(nullptr), fStart(nullptr), fTemp(nullptr), fUseTemp(kFALSE), fRefCount(1), fSpace(0)
0225       {
0226       }
0227       virtual ~EnvironBase() {}
0228       size_t              fIdx;
0229       size_t              fSize;
0230       void*               fObject;
0231       void*               fStart;
0232       void*               fTemp;
0233       union {
0234          Bool_t fUseTemp;
0235          Bool_t fLastValueVecBool;
0236       };
0237       int                 fRefCount;
0238       size_t              fSpace;
0239    };
0240    template <typename T> struct Environ : public EnvironBase {
0241       Environ() : fIterator() {}
0242       typedef T           Iter_t;
0243       Iter_t              fIterator;
0244       T& iter() { return fIterator; }
0245       static void        *Create() {
0246          return new Environ();
0247       }
0248    };
0249 
0250    template <class T, class Q> struct PairHolder {
0251       T first;
0252       Q second;
0253       PairHolder() {}
0254       PairHolder(const PairHolder& c) : first(c.first), second(c.second) {}
0255       virtual ~PairHolder() {}
0256    private:
0257       PairHolder& operator=(const PairHolder&) = delete;
0258    };
0259 
0260    template <class T> struct Address {
0261       virtual ~Address() {}
0262       static void* address(T ref) {
0263          return const_cast<void*>(reinterpret_cast<const void*>(&ref));
0264       }
0265    };
0266 
0267    struct SfinaeHelper {
0268       // Use SFINAE to get the size of the container
0269 
0270       // In general we get the size of the container with the size method
0271       template <class T>
0272       static size_t GetContainerSize(const T& c) {return c.size();}
0273 
0274       // Since forward_list does not provide a size operator, we have to
0275       // use an alternative. This has a cost of course.
0276       template <class T, class ALLOCATOR>
0277       static size_t GetContainerSize(const std::forward_list<T,ALLOCATOR>& c) {return std::distance(c.begin(),c.end());}
0278    };
0279 
0280    /** @class ROOT::Detail::TCollectionProxyInfo::Type
0281     *
0282     * Small helper to encapsulate basic data accesses for
0283     * all STL continers.
0284     *
0285     * @author  M.Frank
0286     * @version 1.0
0287     * @date    10/10/2004
0288     */
0289    template <class T> struct Type
0290       : public Address<TYPENAME T::const_reference>
0291    {
0292       typedef T                      Cont_t;
0293       typedef typename T::iterator   Iter_t;
0294       typedef typename T::value_type Value_t;
0295       typedef Environ<Iter_t>        Env_t;
0296       typedef Env_t                 *PEnv_t;
0297       typedef Cont_t                *PCont_t;
0298       typedef Value_t               *PValue_t;
0299 
0300       virtual ~Type() {}
0301 
0302       static inline PCont_t object(void* ptr)   {
0303          return PCont_t(PEnv_t(ptr)->fObject);
0304       }
0305       static void* size(void* env)  {
0306          PEnv_t  e = PEnv_t(env);
0307          e->fSize   = SfinaeHelper::GetContainerSize(*PCont_t(e->fObject));
0308          return &e->fSize;
0309       }
0310       static void* clear(void* env)  {
0311          object(env)->clear();
0312          return nullptr;
0313       }
0314       static void* first(void* env)  {
0315          PEnv_t  e = PEnv_t(env);
0316          PCont_t c = PCont_t(e->fObject);
0317 #if 0
0318          // Assume iterators do not need destruction
0319          ::new(e->buff) Iter_t(c->begin());
0320 #endif
0321          e->fIterator = c->begin();
0322          e->fSize  = SfinaeHelper::GetContainerSize(*c);
0323          if ( 0 == e->fSize ) return e->fStart = nullptr;
0324          TYPENAME T::const_reference ref = *(e->iter());
0325          return e->fStart = Type<T>::address(ref);
0326       }
0327       static void* next(void* env)  {
0328          PEnv_t  e = PEnv_t(env);
0329          PCont_t c = PCont_t(e->fObject);
0330          for (; e->fIdx > 0 && e->iter() != c->end(); ++(e->iter()), --e->fIdx){ }
0331          // TODO: Need to find something for going backwards....
0332          if ( e->iter() == c->end() ) return nullptr;
0333          TYPENAME T::const_reference ref = *(e->iter());
0334          return Type<T>::address(ref);
0335       }
0336       static void* construct(void *what, size_t size)  {
0337          PValue_t m = PValue_t(what);
0338          for (size_t i=0; i<size; ++i, ++m)
0339             ::new(m) Value_t();
0340          return nullptr;
0341       }
0342       static void* collect(void *coll, void *array)  {
0343          PCont_t  c = PCont_t(coll);
0344          PValue_t m = PValue_t(array);
0345          for (Iter_t i=c->begin(); i != c->end(); ++i, ++m )
0346             ::new(m) Value_t(*i);
0347          return nullptr;
0348       }
0349       static void destruct(void *what, size_t size)  {
0350          PValue_t m = PValue_t(what);
0351          for (size_t i=0; i < size; ++i, ++m )
0352             m->~Value_t();
0353       }
0354 
0355       static const bool fgLargeIterator = sizeof(typename Cont_t::iterator) > fgIteratorArenaSize;
0356       typedef Iterators<Cont_t,fgLargeIterator> Iterators_t;
0357 
0358    };
0359 
0360    /** @class ROOT::Detail::TCollectionProxyInfo::Pushback
0361     *
0362     * Small helper to encapsulate all necessary data accesses for
0363     * containers like vector, list, deque
0364     *
0365     * @author  M.Frank
0366     * @version 1.0
0367     * @date    10/10/2004
0368     */
0369    template <class T> struct Pushback : public Type<T> {
0370       typedef T                      Cont_t;
0371       typedef typename T::iterator   Iter_t;
0372       typedef typename T::value_type Value_t;
0373       typedef Environ<Iter_t>        Env_t;
0374       typedef Env_t                 *PEnv_t;
0375       typedef Cont_t                *PCont_t;
0376       typedef Value_t               *PValue_t;
0377       static void resize(void* obj, size_t n) {
0378          PCont_t c = PCont_t(obj);
0379          c->resize(n);
0380       }
0381       static void* feed(void *from, void *to, size_t size)  {
0382          PCont_t  c = PCont_t(to);
0383          PValue_t m = PValue_t(from);
0384          for (size_t i=0; i<size; ++i, ++m)
0385             c->push_back(*m);
0386          return nullptr;
0387       }
0388       static int value_offset()  {
0389          return 0;
0390       }
0391    };
0392 
0393    /** @class ROOT::Detail::TCollectionProxyInfo::Pushfront
0394     *
0395     * Small helper to encapsulate all necessary data accesses for
0396     * containers like forward_list
0397     *
0398     * @author  D.Piparo
0399     * @version 1.0
0400     * @date    26/02/2015
0401     */
0402    template <class T> struct Pushfront : public Type<T> {
0403       typedef T                      Cont_t;
0404       typedef typename T::iterator   Iter_t;
0405       typedef typename T::value_type Value_t;
0406       typedef Environ<Iter_t>        Env_t;
0407       typedef Env_t                 *PEnv_t;
0408       typedef Cont_t                *PCont_t;
0409       typedef Value_t               *PValue_t;
0410       static void resize(void* obj, size_t n) {
0411          PCont_t c = PCont_t(obj);
0412          c->resize(n);
0413       }
0414       static void* feed(void *from, void *to, size_t size)  {
0415          PCont_t  c = PCont_t(to);
0416          if (size==0) return nullptr;
0417          PValue_t m = &(PValue_t(from)[size-1]); // Take the last item
0418          // Iterate backwards not to revert ordering
0419          for (size_t i=0; i<size; ++i, --m){
0420             c->push_front(*m);
0421          }
0422          return nullptr;
0423       }
0424       static int value_offset()  {
0425          return 0;
0426       }
0427    };
0428 
0429    /** @class ROOT::Detail::TCollectionProxyInfo::Insert
0430     *
0431     * Small helper to encapsulate all necessary data accesses for
0432     * containers like set, multiset etc.
0433     *
0434     * @author  M.Frank
0435     * @version 1.0
0436     * @date    10/10/2004
0437     */
0438    template <class T> struct Insert : public Type<T> {
0439       typedef T                      Cont_t;
0440       typedef typename T::iterator   Iter_t;
0441       typedef typename T::value_type Value_t;
0442       typedef Environ<Iter_t>        Env_t;
0443       typedef Env_t                 *PEnv_t;
0444       typedef Cont_t                *PCont_t;
0445       typedef Value_t               *PValue_t;
0446       static void* feed(void *from, void *to, size_t size)  {
0447          PCont_t  c = PCont_t(to);
0448          PValue_t m = PValue_t(from);
0449          for (size_t i=0; i<size; ++i, ++m)
0450             c->insert(*m);
0451          return nullptr;
0452       }
0453       static void resize(void* /* obj */, size_t )  {
0454          ;
0455       }
0456       static int value_offset()  {
0457          return 0;
0458       }
0459    };
0460 
0461    /** @class ROOT::Detail::TCollectionProxyInfo::MapInsert
0462     *
0463     * Small helper to encapsulate all necessary data accesses for
0464     * containers like set, multiset etc.
0465     *
0466     * @author  M.Frank
0467     * @version 1.0
0468     * @date    10/10/2004
0469     */
0470    template <class T> struct MapInsert : public Type<T> {
0471       typedef T                      Cont_t;
0472       typedef typename T::iterator   Iter_t;
0473       typedef typename T::value_type Value_t;
0474       typedef Environ<Iter_t>        Env_t;
0475       typedef Env_t                 *PEnv_t;
0476       typedef Cont_t                *PCont_t;
0477       typedef Value_t               *PValue_t;
0478       static void* feed(void *from, void *to, size_t size)  {
0479          PCont_t  c = PCont_t(to);
0480          PValue_t m = PValue_t(from);
0481          for (size_t i=0; i<size; ++i, ++m)
0482             c->insert(*m);
0483          return nullptr;
0484       }
0485       static void resize(void* /* obj */, size_t )  {
0486          ;
0487       }
0488       static int value_offset()  {
0489          return ((char*)&((PValue_t(0x1000))->second)) - ((char*)PValue_t(0x1000));
0490       }
0491    };
0492 
0493 
0494    public:
0495       const std::type_info &fInfo;
0496       size_t fIterSize;
0497       size_t fValueDiff;
0498       int    fValueOffset;
0499       void*  (*fSizeFunc)(void*);
0500       void   (*fResizeFunc)(void*,size_t);
0501       void*  (*fClearFunc)(void*);
0502       void*  (*fFirstFunc)(void*);
0503       void*  (*fNextFunc)(void*);
0504       void*  (*fConstructFunc)(void*,size_t);
0505       void   (*fDestructFunc)(void*,size_t);
0506       void*  (*fFeedFunc)(void*,void*,size_t);
0507       void*  (*fCollectFunc)(void*,void*);
0508       void*  (*fCreateEnv)();
0509 
0510       // Set of function of direct iteration of the collections.
0511       void (*fCreateIterators)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy);
0512       // begin_arena and end_arena should contain the location of memory arena  of size fgIteratorSize.
0513       // If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
0514       // Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
0515 
0516       void* (*fCopyIterator)(void *dest, const void *source);
0517       // Copy the iterator source, into dest.   dest should contain should contain the location of memory arena  of size fgIteratorSize.
0518       // If the collection iterator are of that size or less, the iterator will be constructed in place in this location (new with placement)
0519       // Otherwise the iterator will be allocated via a regular new and its address returned by modifying the value of dest.
0520 
0521       void* (*fNext)(void *iter, const void *end);
0522       // iter and end should be pointer to respectively an iterator to be incremented and the result of colleciton.end()
0523       // 'Next' will increment the iterator 'iter' and return 0 if the iterator reached the end.
0524       // If the end is not reached, 'Next' will return the address of the content unless the collection contains pointers in
0525       // which case 'Next' will return the value of the pointer.
0526 
0527       void (*fDeleteSingleIterator)(void *iter);
0528       void (*fDeleteTwoIterators)(void *begin, void *end);
0529       // If the sizeof iterator is greater than fgIteratorArenaSize, call delete on the addresses,
0530       // Otherwise just call the iterator's destructor.
0531 
0532    public:
0533       TCollectionProxyInfo(const std::type_info& info,
0534                            size_t iter_size,
0535                            size_t value_diff,
0536                            int    value_offset,
0537                            void*  (*size_func)(void*),
0538                            void   (*resize_func)(void*,size_t),
0539                            void*  (*clear_func)(void*),
0540                            void*  (*first_func)(void*),
0541                            void*  (*next_func)(void*),
0542                            void*  (*construct_func)(void*,size_t),
0543                            void   (*destruct_func)(void*,size_t),
0544                            void*  (*feed_func)(void*,void*,size_t),
0545                            void*  (*collect_func)(void*,void*),
0546                            void*  (*create_env)(),
0547                            void   (*getIterators)(void *collection, void **begin_arena, void **end_arena, TVirtualCollectionProxy *proxy) = nullptr,
0548                            void*  (*copyIterator)(void *dest, const void *source) = nullptr,
0549                            void*  (*next)(void *iter, const void *end) = nullptr,
0550                            void   (*deleteSingleIterator)(void *iter) = nullptr,
0551                            void   (*deleteTwoIterators)(void *begin, void *end) = nullptr
0552                            ) :
0553          fInfo(info), fIterSize(iter_size), fValueDiff(value_diff),
0554          fValueOffset(value_offset),
0555          fSizeFunc(size_func),fResizeFunc(resize_func),fClearFunc(clear_func),
0556          fFirstFunc(first_func),fNextFunc(next_func),fConstructFunc(construct_func),
0557          fDestructFunc(destruct_func),fFeedFunc(feed_func),fCollectFunc(collect_func),
0558          fCreateEnv(create_env),
0559          fCreateIterators(getIterators),fCopyIterator(copyIterator),fNext(next),
0560          fDeleteSingleIterator(deleteSingleIterator),fDeleteTwoIterators(deleteTwoIterators)
0561       {
0562       }
0563 
0564       /// Generate proxy from template
0565       template <class T> static TCollectionProxyInfo* Generate(const T&)  {
0566          // Generate a TCollectionProxyInfo given a TCollectionProxyInfo::Type
0567          // template (used to described the behavior of the stl collection.
0568          // Typical use looks like:
0569          //      ::ROOT::Detail::TCollectionProxyInfo::Generate(TCollectionProxyInfo::Pushback< std::vector<string> >()));
0570 
0571          PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>* p =
0572             (PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>*)0x1000;
0573          return new TCollectionProxyInfo(typeid(TYPENAME T::Cont_t),
0574                                                sizeof(TYPENAME T::Iter_t),
0575                                                (((char*)&p->second)-((char*)&p->first)),
0576                                                T::value_offset(),
0577                                                T::size,
0578                                                T::resize,
0579                                                T::clear,
0580                                                T::first,
0581                                                T::next,
0582                                                T::construct,
0583                                                T::destruct,
0584                                                T::feed,
0585                                                T::collect,
0586                                                T::Env_t::Create,
0587                                                T::Iterators_t::create,
0588                                                T::Iterators_t::copy,
0589                                                T::Iterators_t::next,
0590                                                T::Iterators_t::destruct1,
0591                                                T::Iterators_t::destruct2);
0592       }
0593 
0594       template <class T> static TCollectionProxyInfo Get(const T&)  {
0595 
0596          // Generate a TCollectionProxyInfo given a TCollectionProxyInfo::Type
0597          // template (used to described the behavior of the stl collection.
0598          // Typical use looks like:
0599          //      ::ROOT::Detail::TCollectionProxyInfo::Get(TCollectionProxyInfo::Pushback< std::vector<string> >()));
0600 
0601          PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>* p =
0602             (PairHolder<TYPENAME T::Value_t, TYPENAME T::Value_t>*)0x1000;
0603          return TCollectionProxyInfo(typeid(TYPENAME T::Cont_t),
0604                                            sizeof(TYPENAME T::Iter_t),
0605                                            (((char*)&p->second)-((char*)&p->first)),
0606                                            T::value_offset(),
0607                                            T::size,
0608                                            T::resize,
0609                                            T::clear,
0610                                            T::first,
0611                                            T::next,
0612                                            T::construct,
0613                                            T::destruct,
0614                                            T::feed,
0615                                            T::collect,
0616                                            T::Env_t::Create);
0617       }
0618 
0619    };
0620 
0621    // This specialization is chosen if T is a vector<bool, A>, irrespective of the nature
0622    // of the allocator A represents.
0623    template <class A> struct TCollectionProxyInfo::Type<std::vector<Bool_t, A>>
0624    : public TCollectionProxyInfo::Address<typename std::vector<Bool_t, A>::const_reference>
0625    {
0626       typedef std::vector<Bool_t, A>       Cont_t;
0627       typedef typename Cont_t::iterator    Iter_t;
0628       typedef typename Cont_t::value_type  Value_t;
0629       typedef Environ<Iter_t>              Env_t;
0630       typedef Env_t                       *PEnv_t;
0631       typedef Cont_t                      *PCont_t;
0632       typedef Value_t                     *PValue_t;
0633 
0634       virtual ~Type() {}
0635 
0636       static inline PCont_t object(void* ptr)   {
0637          return PCont_t(PEnv_t(ptr)->fObject);
0638       }
0639       static void* size(void* env)  {
0640          PEnv_t  e = PEnv_t(env);
0641          e->fSize   = PCont_t(e->fObject)->size();
0642          return &e->fSize;
0643       }
0644       static void* clear(void* env)  {
0645          object(env)->clear();
0646          return nullptr;
0647       }
0648       static void* first(void* env)  {
0649          PEnv_t  e = PEnv_t(env);
0650          PCont_t c = PCont_t(e->fObject);
0651 #if 0
0652          // Assume iterators do not need destruction
0653          ::new(e->buff) Iter_t(c->begin());
0654 #endif
0655          e->fIterator = c->begin();
0656          e->fSize  = c->size();
0657          return nullptr;
0658       }
0659       static void* next(void* env)  {
0660          PEnv_t  e = PEnv_t(env);
0661          PCont_t c = PCont_t(e->fObject);
0662          for (; e->fIdx > 0 && e->iter() != c->end(); ++(e->iter()), --e->fIdx){ }
0663          // TODO: Need to find something for going backwards....
0664          return nullptr;
0665       }
0666       static void* construct(void*,size_t)  {
0667          // Nothing to construct.
0668          return nullptr;
0669       }
0670       static void* collect(void *coll, void *array)  {
0671          PCont_t  c = PCont_t(coll);
0672          PValue_t m = PValue_t(array); // 'start' is a buffer outside the container.
0673          for (Iter_t i=c->begin(); i != c->end(); ++i, ++m )
0674             ::new(m) Value_t(*i);
0675          return nullptr;
0676       }
0677       static void destruct(void*,size_t)  {
0678          // Nothing to destruct.
0679       }
0680 
0681       //static const bool fgLargeIterator = sizeof(Cont_t::iterator) > fgIteratorArenaSize;
0682       //typedef Iterators<Cont_t,fgLargeIterator> Iterators_t;
0683 
0684       struct Iterators {
0685          typedef typename Cont_t::iterator iterator;
0686 
0687          static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
0688             PCont_t c = PCont_t(coll);
0689             new (*begin_arena) iterator(c->begin());
0690             new (*end_arena) iterator(c->end());
0691          }
0692          static void* copy(void *dest_arena, const void *source_ptr) {
0693             const iterator *source = (const iterator *)(source_ptr);
0694             new (dest_arena) iterator(*source);
0695             return dest_arena;
0696          }
0697          static void* next(void *, const void *) {
0698             R__ASSERT(false && "Intentionally not implemented, should use VectorLooper or similar for vector<bool>.");
0699             return {};
0700          }
0701          static void destruct1(void *iter_ptr) {
0702             iterator *start = (iterator *)(iter_ptr);
0703             start->~iterator();
0704          }
0705          static void destruct2(void *begin_ptr, void *end_ptr) {
0706             iterator *start = (iterator *)(begin_ptr);
0707             iterator *end = (iterator *)(end_ptr);
0708             start->~iterator();
0709             end->~iterator();
0710          }
0711       };
0712       typedef Iterators Iterators_t;
0713 
0714    };
0715 
0716    template <class A> struct TCollectionProxyInfo::Pushback<std::vector<Bool_t, A> > : public TCollectionProxyInfo::Type<std::vector<Bool_t, A> > {
0717       typedef std::vector<Bool_t, A>       Cont_t;
0718       typedef typename Cont_t::iterator    Iter_t;
0719       typedef typename Cont_t::value_type  Value_t;
0720       typedef Environ<Iter_t>              Env_t;
0721       typedef Env_t                       *PEnv_t;
0722       typedef Cont_t                      *PCont_t;
0723       typedef Value_t                     *PValue_t;
0724 
0725       static void resize(void* obj,size_t n) {
0726          PCont_t c = PCont_t(obj);
0727          c->resize(n);
0728       }
0729       static void* feed(void* from, void *to, size_t size)  {
0730          PCont_t  c = PCont_t(to);
0731          PValue_t m = PValue_t(from);
0732          for (size_t i=0; i<size; ++i, ++m)
0733             c->push_back(*m);
0734          return nullptr;
0735       }
0736       static int value_offset()  {
0737          return 0;
0738       }
0739    };
0740 
0741    // Need specialization for boolean references due to stupid STL std::vector<bool>
0742    template <class A> struct TCollectionProxyInfo::Address<std::vector<Bool_t, A>> {
0743       virtual ~Address() {}
0744       static void* address(typename std::vector<Bool_t, A>::const_reference) {
0745          R__ASSERT(false && "Intentionally not implemented, should use VectorLooper or other functions specialized for "
0746                             "vector<bool> instead");
0747          return {};
0748       }
0749    };
0750 
0751    template <typename Bitset_t> struct TCollectionProxyInfo::Type<Internal::TStdBitsetHelper<Bitset_t> > : public TCollectionProxyInfo::Address<const Bool_t &>
0752    {
0753       typedef Bitset_t                 Cont_t;
0754       typedef std::pair<size_t,Bool_t> Iter_t;
0755       typedef Bool_t                   Value_t;
0756       typedef Environ<Iter_t>          Env_t;
0757       typedef Env_t                   *PEnv_t;
0758       typedef Cont_t                  *PCont_t;
0759       typedef Value_t                 *PValue_t;
0760 
0761       virtual ~Type() {}
0762 
0763       static inline PCont_t object(void* ptr)   {
0764          return PCont_t(PEnv_t(ptr)->fObject);
0765       }
0766       static void* size(void* env)  {
0767          PEnv_t  e = PEnv_t(env);
0768          e->fSize   = PCont_t(e->fObject)->size();
0769          return &e->fSize;
0770       }
0771       static void* clear(void* env)  {
0772          object(env)->reset();
0773          return nullptr;
0774       }
0775       static void* first(void* env)  {
0776          PEnv_t  e = PEnv_t(env);
0777          PCont_t c = PCont_t(e->fObject);
0778          e->fIterator.first = 0;
0779          e->fIterator.second = c->size() > 0 ? c->test(e->fIterator.first) : false ;  // Iterator actually hold the value.
0780          e->fSize  = c->size();
0781          return &(e->fIterator.second);
0782       }
0783       static void* next(void* env)  {
0784          PEnv_t  e = PEnv_t(env);
0785          PCont_t c = PCont_t(e->fObject);
0786          for (; e->fIdx > 0 && e->fIterator.first != c->size(); ++(e->fIterator.first), --e->fIdx){ }
0787          e->fIterator.second = (e->fIterator.first != c->size()) ? c->test(e->fIterator.first) : false;
0788          return &(e->fIterator.second);
0789       }
0790       static void* construct(void*,size_t)  {
0791          // Nothing to construct.
0792          return nullptr;
0793       }
0794       static void* collect(void *coll, void *array)  {
0795          PCont_t  c = PCont_t(coll);
0796          PValue_t m = PValue_t(array); // 'start' is a buffer outside the container.
0797          for (size_t i=0; i != c->size(); ++i, ++m )
0798             *m = c->test(i);
0799          return nullptr;
0800       }
0801       static void destruct(void*,size_t)  {
0802          // Nothing to destruct.
0803       }
0804 
0805       //static const bool fgLargeIterator = sizeof(typename Cont_t::iterator) > fgIteratorArenaSize;
0806       //typedef Iterators<Cont_t,fgLargeIterator> Iterators_t;
0807 
0808       struct Iterators {
0809          union PtrSize_t { size_t fIndex; void *fAddress; };
0810          typedef std::pair<PtrSize_t,Bool_t> iterator;
0811          // In the end iterator we store the bitset pointer
0812          // and do not use the 'second' part of the pair.
0813          // In the other iterator we store the index
0814          // and the value.
0815 
0816          static void create(void *coll, void **begin_arena, void **end_arena, TVirtualCollectionProxy*) {
0817             iterator *begin = new (*begin_arena) iterator;
0818             begin->first.fIndex = 0;
0819             begin->second = false;
0820             iterator *end = new (*end_arena) iterator;
0821             end->first.fAddress = coll;
0822             end->second = false;
0823          }
0824          static void* copy(void *dest_arena, const void *source_ptr) {
0825             const iterator *source = (const iterator *)(source_ptr);
0826             new (dest_arena) iterator(*source);
0827             return dest_arena;
0828          }
0829          static void* next(void *iter_loc, const void *end_loc) {
0830             const iterator *end = (const iterator *)(end_loc);
0831             PCont_t c = (PCont_t)end->first.fAddress;
0832             iterator *iter = (iterator *)(iter_loc);
0833             if (iter->first.fIndex != c->size()) {
0834                iter->second = c->test(iter->first.fIndex);
0835                ++(iter->first.fIndex);
0836                return &(iter->second);
0837             } else {
0838                return nullptr;
0839             }
0840          }
0841          static void destruct1(void *iter_ptr) {
0842             iterator *start = (iterator *)(iter_ptr);
0843             start->~iterator();
0844          }
0845          static void destruct2(void *begin_ptr, void *end_ptr) {
0846             iterator *start = (iterator *)(begin_ptr);
0847             iterator *end = (iterator *)(end_ptr);
0848             start->~iterator();
0849             end->~iterator();
0850          }
0851       };
0852       typedef Iterators Iterators_t;
0853    };
0854 
0855    template <typename Bitset_t>
0856    struct TCollectionProxyInfo::Pushback<Internal::TStdBitsetHelper<Bitset_t>  > : public TCollectionProxyInfo::Type<Internal::TStdBitsetHelper<Bitset_t> > {
0857       using InfoBase_t = TCollectionProxyInfo::Type<Internal::TStdBitsetHelper<Bitset_t> >;
0858       using typename InfoBase_t::Cont_t;
0859       using typename InfoBase_t::Iter_t;
0860       using typename InfoBase_t::Value_t;
0861       using typename InfoBase_t::Env_t;
0862       using typename InfoBase_t::PEnv_t;
0863       using typename InfoBase_t::PCont_t;
0864       using typename InfoBase_t::PValue_t;
0865 
0866       static void resize(void*,size_t)  {
0867       }
0868       static void* feed(void *from, void *to, size_t size)  {
0869          PCont_t  c = PCont_t(to);
0870          PValue_t m = PValue_t(from);
0871          for (size_t i=0; i<size; ++i, ++m)
0872             c->set(i,*m);
0873          return nullptr;
0874       }
0875       static int value_offset()  {
0876          return 0;
0877       }
0878    };
0879 
0880 } // namespace Detail
0881 
0882 // For (reasonable) backward compatibility:
0883 using namespace Detail;
0884 } // namespace ROOT
0885 
0886 #endif