foreach.h

Go to the documentation of this file.
00001 #ifndef CXXTLS_FOREACH_H_INCLUDED
00002 #define CXXTLS_FOREACH_H_INCLUDED
00003 
00004 namespace cxxtls
00005 {
00006 namespace foreach_helpers
00007 {
00008 
00009 typedef unsigned long long size_t;
00010 
00011 // note:  std::set::iterator::operator*() returns a const reference, 
00012 // instead of a mutable reference like all other containers do.
00013 // sooo, we have to figure out what the constness of the *iterator is
00014 // whenever we dereference the the loop iterators.
00015 
00016 template<class Container>
00017 struct iteratorReturnsConst
00026 {
00027     // Container must have an iterator member type
00028 
00029     typedef typename Container::iterator Iterator;  
00030 
00031     template<class U>  
00032     static char is_const_tester(const U &);   // takes only const params
00033 
00034     template<class V>
00035     static int  is_const_tester(V &); // takes any parameter type 
00036 
00037     static Iterator it;  // never gets instantiated
00038 
00039     enum c {
00040               value = (
00041                          sizeof(char) == sizeof(
00042                                                  is_const_tester(*it) 
00043                                                )
00044                       )
00045            };
00046 };
00047 
00048 
00049 
00050 template<bool, class ZeroClass, class OneClass> 
00051 struct  EvalTypeIf
00059 {
00060 };
00061 
00062 template<class ZeroClass, class OneClass> 
00063 struct  EvalTypeIf<0, ZeroClass, OneClass>
00064 {
00065   typedef ZeroClass type;  // the false case:
00066 };
00067 
00068 template<class ZeroClass, class OneClass> 
00069 struct  EvalTypeIf<1, ZeroClass, OneClass>
00070 {
00071   typedef OneClass type;  // the true case
00072 };
00073 
00074 template<class Container>
00075 struct IteratorReferent
00087 {
00088     typedef typename EvalTypeIf<  iteratorReturnsConst<Container>::value, 
00089                                   typename Container::value_type, 
00090                                   const typename Container::value_type
00091                                >::type
00092             type;
00093 };
00094 
00095 template<class Container, size_t N>
00096 struct IteratorReferent<Container [N]>
00097    // see above
00098 {
00099     typedef Container type;
00100 };
00101 
00102 template<class Container, size_t N>
00103 struct IteratorReferent<const Container [N]>
00104    // see above
00105 {
00106     typedef const Container type;
00107 };
00108 
00109 
00110 struct AnyTypeBase
00111   //
00112   //  References to objects of AnyTypeBase will be cast to references to
00113   //  objects of type AnyType<T>, where T is defined externally to
00114   //  AnyType or their uses.
00115   //
00116 {
00117    operator bool() const { return 0; }
00118 };
00119 
00120 template<class T>
00121 struct AnyType
00122     //
00123     //  A wrapper around any type.  Sometimes T is a reference and sometimes
00124     //  it is a real value.
00125     //
00126 : public AnyTypeBase
00127 {
00128    typedef T value_type;
00129 
00130    mutable T value_;
00131 
00132    AnyType(T t)
00133    : value_(t)
00134    {
00135    }
00136 
00137 };
00138 
00139 template<class T>
00140 struct IteratorWrapper
00141    //
00142    //  An object that can hold any kind of iterator.  The template parameter
00143    //  T refers to the STL style container whose iterator is being held.
00144    //
00145    //  There is a template specialization below that handles arrays.
00146    //
00147 {
00148    typename T::iterator iterator_;
00149 
00150    IteratorWrapper(typename T::iterator t)
00151    : iterator_(t)
00152    {
00153    }
00154 
00155    typename IteratorReferent<T>::type &operator*() { return *iterator_; }
00156 
00157    typename T::value_type const &operator*() const { return *iterator_; }
00158 
00159 };
00160 
00161 template<class T>
00162 struct IteratorWrapper<T *>
00167 {
00168    T* iterator_;
00169 
00170    IteratorWrapper(T const * t)
00171    : iterator_(const_cast<T*>(t))
00172    {
00173    }
00174 
00175    T &operator*() { return *iterator_; }
00176 
00177    T const &operator*() const { return *iterator_; }
00178 
00179 };
00180 
00181 
00182 template<class T>
00183 inline
00184 AnyType< T & > 
00185 getContainer(T const& v) 
00186     
00187 
00188 
00189 
00190 { 
00191     return const_cast<T&>(v) ; 
00192 } 
00193 
00194 template<class T, size_t N>
00195 inline
00196 AnyType< T const* > 
00197 getContainer(T const (&v)[N]) 
00198     
00199 
00200 
00201 
00202 { 
00203     T (&array)[N] = const_cast< T (&)[N] >(v); 
00204 
00205     return &array[0];
00206 } 
00207 
00208 
00209 template<class T>
00210 inline
00211 AnyType< IteratorWrapper<T> >
00212 getBegin(AnyTypeBase const &b, T const *) 
00213     
00214 
00215 
00216 
00217 
00218 
00219 
00220 { 
00221     AnyType< T& > const &container = static_cast< AnyType<T&> const& > (b);
00222 
00223     return IteratorWrapper<T>(container.value_.begin());
00224 
00225 }
00226 
00227 
00228 template<class T, size_t N>
00229 inline
00230 AnyType< IteratorWrapper<T*> >
00231 getBegin(AnyTypeBase const &b, T const (*)[N]) 
00232     
00233 
00234 
00235 
00236 
00237 
00238 
00239 {
00240     AnyTypeBase &mutableBase = const_cast<AnyTypeBase&>(b);
00241 
00242     AnyType< T const* > const &container = static_cast< AnyType< T const* > &> (mutableBase);
00243 
00244     return IteratorWrapper<T*>(container.value_);
00245 
00246 }
00247 
00248 
00249 template<class T>
00250 inline
00251 AnyType< IteratorWrapper<T> > 
00252 getEnd(AnyTypeBase const &b, T const *) 
00253     
00254 
00255 
00256 
00257 
00258 
00259 
00260 { 
00261     AnyType< T& > const &container = static_cast< AnyType<T&> const& > (b);
00262 
00263     return IteratorWrapper<T>(container.value_.end());
00264 }
00265 
00266 template<class T, size_t N>
00267 inline
00268 AnyType< IteratorWrapper<T*> >
00269 getEnd(AnyTypeBase const &b, T const (*)[N]) 
00270     
00271 
00272 
00273 
00274 
00275 
00276 
00277 {
00278     AnyTypeBase &mutableBase = const_cast<AnyTypeBase&>(b);
00279 
00280     AnyType< T const* > const &container = static_cast< AnyType< T const* > &> (mutableBase);
00281 
00282     return IteratorWrapper<T*>(container.value_ + N);
00283 
00284 }
00285 
00286 
00287 
00288 template<class Container>
00289 inline typename IteratorReferent<Container>::type
00290 &deref(AnyTypeBase const & current, Container *)
00296 {
00297     typedef IteratorWrapper<Container> IteratorType;
00298 
00299     AnyType<IteratorType> const &cur = static_cast<AnyType<IteratorType> const &>(current);
00300 
00301     // cur is a const reference to an AnyType which declares its member to be mutable
00302 
00303     typename Container::value_type const &cref =  *cur.value_;
00304 
00305     return const_cast< typename IteratorReferent<Container>::type &>(cref);
00306 }
00307 
00308 template<class Container>
00309 inline
00310 const typename Container::value_type &deref(AnyTypeBase const & current,
00311                                       Container const *
00312                                      )
00318 {
00319     AnyType< IteratorWrapper<Container> > const &cur = 
00320                                                static_cast<AnyType< IteratorWrapper<Container> > const &>(current);
00321 
00322     // cur is a const reference to an AnyType which declares its member to be mutable
00323 
00324     return *cur.value_;
00325 }
00326 
00327 
00328 template<class T, size_t N>
00329 inline
00330 T const &deref(AnyTypeBase const & current,
00331           T const (*)[N]
00332          )
00338 {
00339     AnyType< IteratorWrapper<T*> > const &cur = 
00340                                                static_cast< AnyType< IteratorWrapper<T*> > const &>(current);
00341 
00342     // cur is a const reference to an AnyType which declares its member to be mutable
00343 
00344     return *cur.value_;
00345 }
00346 
00347 template<class T, size_t N>
00348 inline
00349 T  &deref(AnyTypeBase const & current,
00350           T (*)[N]
00351          )
00357 {
00358     AnyType< IteratorWrapper<T*> > const &cur = 
00359                                                static_cast< AnyType< IteratorWrapper<T*> > const &>(current);
00360 
00361     // cur is a const reference to an AnyType which declares its member to be mutable
00362 
00363     return *cur.value_;
00364 }
00365 
00366 
00367 
00368 template<class Container>
00369 inline
00370 bool continuing(AnyTypeBase const &current, AnyTypeBase const &last, Container const *)
00375 {
00376     AnyType< IteratorWrapper<Container> > const &cur = 
00377                                                static_cast<AnyType<IteratorWrapper<Container> > const &>(current);
00378 
00379     AnyType< IteratorWrapper<Container> > const &end = 
00380                                                static_cast<AnyType< IteratorWrapper<Container>  > const &>(last);
00381 
00382    return cur.value_.iterator_ != end.value_.iterator_;
00383 }
00384 
00385 
00386 template<class T, size_t N>
00387 inline
00388 bool continuing(AnyTypeBase const &current, AnyTypeBase const &last, T const (*)[N])
00393 {
00394     AnyType< IteratorWrapper<T*> > const &cur = 
00395                                                static_cast<AnyType<IteratorWrapper<T*> > const &>(current);
00396 
00397     AnyType< IteratorWrapper<T*> > const &end = 
00398                                                static_cast<AnyType< IteratorWrapper<T*>  > const &>(last);
00399 
00400    return cur.value_.iterator_ != end.value_.iterator_;
00401 }
00402 
00403             
00404 template<class Container>
00405 inline
00406 bool next(AnyTypeBase const &current, AnyTypeBase const &last, Container const *)
00413 {
00414 
00415     AnyType< IteratorWrapper<Container> > const &cur = 
00416                                                static_cast<AnyType< IteratorWrapper<Container> > const &>(current);
00417 
00418     AnyType< IteratorWrapper<Container> > const &end = 
00419                                                static_cast<AnyType< IteratorWrapper<Container> > const &>(last);
00420 
00421     if(cur.value_.iterator_ != end.value_.iterator_)
00422     {
00423        ++cur.value_.iterator_;
00424     }
00425     else
00426     {
00427        throw AnyType<int>(0); // no can do big guy -- end of list
00428     }
00429 
00430     return true;
00431 }
00432 
00433 template<class T, size_t N>
00434 inline
00435 bool next(AnyTypeBase const &current, AnyTypeBase const &last, T const (*)[N])
00442 {
00443 
00444     AnyType< IteratorWrapper<T*> > const &cur = 
00445                                                static_cast<AnyType< IteratorWrapper<T*> > const &>(current);
00446 
00447     AnyType< IteratorWrapper<T*> > const &end = 
00448                                                static_cast<AnyType< IteratorWrapper<T*> > const &>(last);
00449 
00450     if(cur.value_.iterator_ != end.value_.iterator_)
00451     {
00452        ++cur.value_.iterator_;
00453     }
00454     else
00455     {
00456        throw AnyType<int>(0); // no can do big guy -- end of list
00457     }
00458 
00459     return true;
00460 
00461 }
00462 
00463 
00464 } // namespace foreach_helpers
00465 } // namespace cxxtls
00466 
00477 
00478 #define CXXTLS_NULL_TYPE_PTR(bag) \
00479    (true?0 : &bag)
00480 
00481 
00485 #define CXXTLS_FENS(n)  cxxtls::foreach_helpers::n
00486 
00487 
00491 #define CXXTLS_FEV(n)   cxxtls_foreach_var_##n
00492 
00493 
00511 
00512 #if 0
00513 // my original logic
00514 
00515 #define CXXTLS_FOREACH(loopVar, bag)                                                           \
00516     if( CXXTLS_FENS(AnyTypeBase) const & CXXTLS_FEV(cnt) =                                     \
00517          CXXTLS_FENS(getContainer)(bag) )                                              {} else \
00518     if( CXXTLS_FENS(AnyTypeBase) const & CXXTLS_FEV(cur) =                                     \
00519          CXXTLS_FENS(getBegin)(CXXTLS_FEV(cnt), CXXTLS_NULL_TYPE_PTR(bag)))            {} else \
00520     if( CXXTLS_FENS(AnyTypeBase) const &  CXXTLS_FEV(end) =                                    \
00521          CXXTLS_FENS(getEnd)(CXXTLS_FEV(cnt), CXXTLS_NULL_TYPE_PTR(bag)))              {} else \
00522     for( bool done=false;                                                                      \
00523          CXXTLS_FENS(continuing)(CXXTLS_FEV(cur), CXXTLS_FEV(end), CXXTLS_NULL_TYPE_PTR(bag)); \
00524          done=false                                                                            \
00525        )                                                                                       \
00526     for( loopVar = CXXTLS_FENS(deref)( CXXTLS_FEV(cur), CXXTLS_NULL_TYPE_PTR(bag));            \
00527          !done;                                                                                \
00528          (done=true) &&                                                                        \
00529              CXXTLS_FENS(next)(CXXTLS_FEV(cur), CXXTLS_FEV(end), CXXTLS_NULL_TYPE_PTR(bag))    \
00530        )
00531 #endif
00532 
00533 
00534 // logic tweaked by comparison of the for loops at the bottom with boost to overcome the
00535 // bug that prevented break from working inside the loop.
00536 
00537 #define CXXTLS_FOREACH(loopVar, bag)                                                           \
00538     if( CXXTLS_FENS(AnyTypeBase) const & CXXTLS_FEV(cnt) =                                     \
00539          CXXTLS_FENS(getContainer)(bag) )                                              {} else \
00540     if( CXXTLS_FENS(AnyTypeBase) const & CXXTLS_FEV(cur) =                                     \
00541          CXXTLS_FENS(getBegin)(CXXTLS_FEV(cnt), CXXTLS_NULL_TYPE_PTR(bag)))            {} else \
00542     if( CXXTLS_FENS(AnyTypeBase) const &  CXXTLS_FEV(end) =                                    \
00543          CXXTLS_FENS(getEnd)(CXXTLS_FEV(cnt), CXXTLS_NULL_TYPE_PTR(bag)))              {} else \
00544     for( bool fcCnTiNuE=true;                                                                 \
00545          fcCnTiNuE && CXXTLS_FENS(continuing)(CXXTLS_FEV(cur), CXXTLS_FEV(end), CXXTLS_NULL_TYPE_PTR(bag)); \
00546          (fcCnTiNuE? CXXTLS_FENS(next)(CXXTLS_FEV(cur), CXXTLS_FEV(end), CXXTLS_NULL_TYPE_PTR(bag)) : 0 )   \
00547        )                                                                                       \
00548     if((fcCnTiNuE=false)) {} else                                                             \
00549     for( loopVar = CXXTLS_FENS(deref)( CXXTLS_FEV(cur), CXXTLS_NULL_TYPE_PTR(bag));            \
00550          !fcCnTiNuE;                                                                          \
00551          fcCnTiNuE=true                                                                       \
00552        )
00553 
00554 
00555 
00556 #endif
Generated on Wed Feb 29 22:50:04 2012 for CXXUtilities by  doxygen 1.6.3