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
00012
00013
00014
00015
00016 template<class Container>
00017 struct iteratorReturnsConst
00026 {
00027
00028
00029 typedef typename Container::iterator Iterator;
00030
00031 template<class U>
00032 static char is_const_tester(const U &);
00033
00034 template<class V>
00035 static int is_const_tester(V &);
00036
00037 static Iterator it;
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;
00066 };
00067
00068 template<class ZeroClass, class OneClass>
00069 struct EvalTypeIf<1, ZeroClass, OneClass>
00070 {
00071 typedef OneClass type;
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
00098 {
00099 typedef Container type;
00100 };
00101
00102 template<class Container, size_t N>
00103 struct IteratorReferent<const Container [N]>
00104
00105 {
00106 typedef const Container type;
00107 };
00108
00109
00110 struct AnyTypeBase
00111
00112
00113
00114
00115
00116 {
00117 operator bool() const { return 0; }
00118 };
00119
00120 template<class T>
00121 struct AnyType
00122
00123
00124
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
00143
00144
00145
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
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
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
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
00362
00363 return *cur.value_;
00364 }
00365
00366
00367
00368 template<class Container>
00369 inline
00370 bool continuing(AnyTypeBase const ¤t, 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 ¤t, 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 ¤t, 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);
00428 }
00429
00430 return true;
00431 }
00432
00433 template<class T, size_t N>
00434 inline
00435 bool next(AnyTypeBase const ¤t, 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);
00457 }
00458
00459 return true;
00460
00461 }
00462
00463
00464 }
00465 }
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
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
00535
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