00001
00084 #ifndef GALOIS_TWO_LEVEL_ITER_H
00085 #define GALOIS_TWO_LEVEL_ITER_H
00086
00087 #include "Galois/config.h"
00088
00089 #include <iterator>
00090 #include GALOIS_CXX11_STD_HEADER(functional)
00091 #include GALOIS_CXX11_STD_HEADER(type_traits)
00092
00093 #include <cstdlib>
00094 #include <cassert>
00095
00096 namespace Galois {
00097
00098 namespace TwoLevelIteratorImpl {
00099 template <typename Iter>
00100 void safe_decrement (Iter& it, const Iter& beg, const Iter& end
00101 , std::forward_iterator_tag) {
00102
00103 Iter next = beg;
00104 Iter curr (next);
00105
00106 while (next != it) {
00107 curr = next;
00108 assert (next != end);
00109 ++next;
00110 }
00111
00112 assert (next == it);
00113 assert (curr != it);
00114
00115 it = curr;
00116 }
00117
00118 template <typename Iter>
00119 void safe_decrement (Iter& it, const Iter& beg, const Iter& end
00120 , std::bidirectional_iterator_tag) {
00121 assert (it != beg);
00122 --it;
00123 }
00124
00125 template <typename Iter>
00126 void safe_decrement (Iter& it, const Iter& beg, const Iter& end) {
00127 safe_decrement (it, beg, end
00128 , typename std::iterator_traits<Iter>::iterator_category ());
00129 }
00130 }
00131
00133 template <typename Outer, typename Inner, typename InnerBegFn, typename InnerEndFn>
00134 class TwoLevelIterBase {
00135
00136 protected:
00137
00138 Outer m_beg_outer;
00139 Outer m_end_outer;
00140 Outer m_outer;
00141 Inner m_inner;
00142
00143 InnerBegFn innerBegFn;
00144 InnerEndFn innerEndFn;
00145
00146
00147 inline bool outerAtBegin () const {
00148 return m_outer == m_beg_outer;
00149 }
00150
00151 inline bool outerAtEnd () const {
00152 return m_outer == m_end_outer;
00153 }
00154
00155 inline bool outerEmpty () const {
00156 return m_beg_outer == m_end_outer;
00157 }
00158
00159 inline Inner innerBegin () {
00160 assert (!outerEmpty ());
00161 assert (!outerAtEnd ());
00162
00163 return innerBegFn (*m_outer);
00164 }
00165
00166 inline Inner innerEnd () {
00167 assert (!outerEmpty ());
00168 assert (!outerAtEnd ());
00169
00170 return innerEndFn (*m_outer);
00171 }
00172
00173 inline bool innerAtBegin () const {
00174 return m_inner == const_cast<TwoLevelIterBase*> (this)->innerBegin ();
00175 }
00176
00177 inline bool innerAtEnd () const {
00178 return m_inner == const_cast<TwoLevelIterBase*> (this)->innerEnd ();
00179 }
00180
00181 TwoLevelIterBase ():
00182 m_beg_outer (),
00183 m_end_outer (),
00184 m_outer (),
00185 m_inner (),
00186 innerBegFn (),
00187 innerEndFn ()
00188 {}
00189
00190 TwoLevelIterBase (
00191 Outer beg_outer,
00192 Outer end_outer,
00193 InnerBegFn innerBegFn,
00194 InnerEndFn innerEndFn)
00195 :
00196 m_beg_outer (beg_outer),
00197 m_end_outer (end_outer),
00198 m_outer (m_beg_outer),
00199 m_inner (),
00200 innerBegFn (innerBegFn),
00201 innerEndFn (innerEndFn)
00202 {}
00203
00204 };
00205
00206
00208 template <typename Outer, typename Inner, typename InnerBegFn, typename InnerEndFn>
00209 class TwoLevelFwdIter:
00210 public std::iterator_traits<Inner>,
00211 public TwoLevelIterBase<Outer, Inner, InnerBegFn, InnerEndFn> {
00212
00213 protected:
00214
00215 typedef std::iterator_traits<Inner> Traits;
00216 typedef TwoLevelIterBase<Outer, Inner, InnerBegFn, InnerEndFn> Base;
00217
00218
00219 void nextOuter () {
00220 assert (!Base::outerAtEnd ());
00221 assert (!Base::outerEmpty ());
00222 ++Base::m_outer;
00223 if (!Base::outerAtEnd ()) {
00224 Base::m_inner = Base::innerBegin ();
00225 }
00226 }
00227
00228 void seekValidBegin () {
00229 while (!Base::outerAtEnd () && Base::innerAtEnd ()) {
00230 nextOuter ();
00231 }
00232 }
00233
00234
00235 void step_forward () {
00236 assert (!Base::innerAtEnd ());
00237 ++Base::m_inner;
00238
00239 if (Base::innerAtEnd ()) {
00240 seekValidBegin ();
00241 }
00242 }
00243
00244 bool is_equal (const TwoLevelFwdIter& that) const {
00245
00246
00247
00248
00249 assert (this->m_end_outer == that.m_end_outer);
00250
00251 return (this->m_outer == that.m_outer)
00252 && (Base::outerAtEnd () || (this->m_inner == that.m_inner));
00253 }
00254
00255
00256 public:
00257
00258 TwoLevelFwdIter (): Base () {}
00259
00260 TwoLevelFwdIter (
00261 Outer beg_outer,
00262 Outer end_outer,
00263 InnerBegFn innerBegFn,
00264 InnerEndFn innerEndFn)
00265 :
00266 Base (beg_outer, end_outer, innerBegFn, innerEndFn)
00267 {
00268
00269 if (!Base::outerAtEnd ()) {
00270 Base::m_inner = Base::innerBegin ();
00271 seekValidBegin ();
00272 }
00273 }
00274
00275 typename Traits::reference operator * () const {
00276 return *Base::m_inner;
00277 }
00278
00279 typename Traits::pointer operator -> () const {
00280 return Base::m_inner->operator -> ();
00281 }
00282
00283 TwoLevelFwdIter& operator ++ () {
00284 step_forward ();
00285 return *this;
00286 }
00287
00288 TwoLevelFwdIter operator ++ (int) {
00289 TwoLevelFwdIter tmp (*this);
00290 step_forward ();
00291 return tmp;
00292 }
00293
00294 friend bool operator == (const TwoLevelFwdIter& left, const TwoLevelFwdIter& right) {
00295 return left.is_equal (right);
00296 }
00297
00298 friend bool operator != (const TwoLevelFwdIter& left, const TwoLevelFwdIter& right) {
00299 return !left.is_equal (right);
00300 }
00301
00302
00303 };
00304
00306 template <typename Outer, typename Inner, typename InnerBegFn, typename InnerEndFn>
00307 class TwoLevelBiDirIter: public TwoLevelFwdIter<Outer, Inner, InnerBegFn, InnerEndFn> {
00308
00309 protected:
00310 typedef TwoLevelFwdIter<Outer, Inner, InnerBegFn, InnerEndFn> FwdBase;
00311
00312 protected:
00313 void prevOuter () {
00314 assert (!FwdBase::outerAtBegin ());
00315 assert (!FwdBase::outerEmpty ());
00316
00317 TwoLevelIteratorImpl::safe_decrement (FwdBase::m_outer, FwdBase::m_beg_outer, FwdBase::m_end_outer);
00318
00319 FwdBase::m_inner = FwdBase::innerEnd ();
00320 }
00321
00322
00323 void step_backward () {
00324 assert (!FwdBase::outerEmpty ());
00325 assert (!FwdBase::outerAtBegin ());
00326
00327
00328
00329
00330 if (FwdBase::outerAtEnd ()) {
00331 prevOuter ();
00332 }
00333
00334 while (FwdBase::innerAtBegin ()) {
00335 assert (!FwdBase::outerAtBegin ());
00336 prevOuter ();
00337 }
00338
00339 assert (FwdBase::innerAtBegin () ? FwdBase::outerAtBegin () : true);
00340
00341 --FwdBase::m_inner;
00342 }
00343
00344 public:
00345
00346 TwoLevelBiDirIter (): FwdBase () {}
00347
00348 TwoLevelBiDirIter (
00349 Outer beg_outer,
00350 Outer end_outer,
00351 InnerBegFn innerBegFn,
00352 InnerEndFn innerEndFn)
00353 :
00354 FwdBase (beg_outer, end_outer, innerBegFn, innerEndFn)
00355 {}
00356
00357
00358 TwoLevelBiDirIter& operator -- () {
00359 step_backward ();
00360 return *this;
00361 }
00362
00363 TwoLevelBiDirIter operator -- (int) {
00364 TwoLevelBiDirIter tmp (*this);
00365 step_backward ();
00366 return tmp;
00367 }
00368 };
00369
00370
00372 template <typename Outer, typename Inner, typename InnerBegFn, typename InnerEndFn>
00373 class TwoLevelRandIter: public TwoLevelBiDirIter<Outer, Inner, InnerBegFn, InnerEndFn> {
00374
00375 protected:
00376 typedef TwoLevelBiDirIter<Outer, Inner, InnerBegFn, InnerEndFn> BiDirBase;
00377
00378 typedef typename BiDirBase::Traits::difference_type Diff_ty;
00379
00380 void jump_forward (const Diff_ty d) {
00381 assert (!BiDirBase::outerEmpty ());
00382
00383 if (d < 0) {
00384 jump_backward (-d);
00385
00386 } else {
00387 Diff_ty rem (d);
00388
00389 while (rem > 0) {
00390 assert (!BiDirBase::outerAtEnd ());
00391
00392 Diff_ty avail = std::distance (BiDirBase::m_inner, BiDirBase::innerEnd ());
00393 assert (avail >= 0);
00394
00395 if (rem > avail) {
00396 rem -= avail;
00397 assert (!BiDirBase::outerAtEnd ());
00398 BiDirBase::nextOuter ();
00399
00400 } else {
00401 BiDirBase::m_inner += rem;
00402 rem = 0;
00403 }
00404
00405 BiDirBase::seekValidBegin ();
00406 }
00407 }
00408 }
00409
00410 void jump_backward (const Diff_ty d) {
00411 assert (!BiDirBase::outerEmpty ());
00412
00413 if (d < 0) {
00414 jump_forward (-d);
00415
00416 } else {
00417
00418
00419 Diff_ty rem (d);
00420
00421 if ((rem > 0) && BiDirBase::outerAtEnd ()) {
00422 BiDirBase::prevOuter ();
00423
00424 }
00425
00426 while (rem > 0) {
00427 Diff_ty avail = std::distance (BiDirBase::innerBegin (), BiDirBase::m_inner);
00428 assert (avail >= 0);
00429
00430 if (rem > avail) {
00431 rem -= avail;
00432 assert (!BiDirBase::outerAtBegin ());
00433 BiDirBase::prevOuter ();
00434
00435 } else {
00436
00437 BiDirBase::m_inner -= rem;
00438 rem = 0;
00439 break;
00440 }
00441 }
00442 }
00443 }
00444
00445 Diff_ty compute_dist (const TwoLevelRandIter& that) const {
00446
00447 if (std::distance (this->m_outer, that.m_outer) < 0) {
00448 return -(that.compute_dist (*this));
00449
00450 } else if (this->m_outer == that.m_outer) {
00451 if (!BiDirBase::outerAtEnd ()) {
00452 return std::distance (this->m_inner, that.m_inner);
00453
00454 } else {
00455 return 0;
00456 }
00457
00458 } else {
00459
00460 assert (std::distance (this->m_outer, that.m_outer) > 0);
00461 assert (!BiDirBase::outerAtEnd ());
00462
00463 TwoLevelRandIter tmp (*this);
00464
00465 Diff_ty d = tmp.m_inner - tmp.m_inner;
00466
00467 while (tmp.m_outer != that.m_outer) {
00468 d += std::distance (tmp.m_inner, tmp.innerEnd ());
00469 tmp.nextOuter ();
00470 }
00471
00472 assert (tmp.m_outer == that.m_outer);
00473
00474 if (tmp.m_outer != tmp.m_end_outer) {
00475 d += std::distance (tmp.m_inner, that.m_inner);
00476 }
00477
00478 assert (d >= 0);
00479
00480 return d;
00481 }
00482 }
00483
00484
00485 public:
00486
00487 TwoLevelRandIter (): BiDirBase () {}
00488
00489 TwoLevelRandIter (
00490 Outer beg_outer,
00491 Outer end_outer,
00492 InnerBegFn innerBegFn,
00493 InnerEndFn innerEndFn)
00494 : BiDirBase (beg_outer, end_outer, innerBegFn, innerEndFn) {}
00495
00496 TwoLevelRandIter& operator += (Diff_ty d) {
00497 jump_forward (d);
00498 return *this;
00499 }
00500
00501 TwoLevelRandIter& operator -= (Diff_ty d) {
00502 jump_backward (d);
00503 return *this;
00504 }
00505
00506 friend TwoLevelRandIter operator + (const TwoLevelRandIter& it, Diff_ty d) {
00507 TwoLevelRandIter tmp (it);
00508 tmp += d;
00509 return tmp;
00510 }
00511
00512 friend TwoLevelRandIter operator + (Diff_ty d, const TwoLevelRandIter& it) {
00513 return (it + d);
00514 }
00515
00516 friend TwoLevelRandIter operator - (const TwoLevelRandIter& it, Diff_ty d) {
00517 TwoLevelRandIter tmp (it);
00518 tmp -= d;
00519 return tmp;
00520 }
00521
00522
00523 friend Diff_ty operator - (const TwoLevelRandIter& left, const TwoLevelRandIter& right) {
00524
00525 return right.compute_dist (left);
00526 }
00527
00528 typename BiDirBase::Traits::reference operator [] (Diff_ty d) const {
00529 return *((*this) + d);
00530 }
00531
00532 friend bool operator < (const TwoLevelRandIter& left, const TwoLevelRandIter& right) {
00533 return ((left.m_outer == right.m_outer) ? (left.m_inner < right.m_inner) : (left.m_outer < right.m_outer));
00534 }
00535
00536 friend bool operator <= (const TwoLevelRandIter& left, const TwoLevelRandIter& right) {
00537 return (left < right) || (left == right);
00538 }
00539
00540 friend bool operator > (const TwoLevelRandIter& left, const TwoLevelRandIter& right) {
00541 return !(left <= right);
00542 }
00543
00544 friend bool operator >= (const TwoLevelRandIter& left, const TwoLevelRandIter& right) {
00545 return !(left < right);
00546 }
00547 };
00548
00549 namespace TwoLevelIteratorImpl {
00550
00551 template <typename Outer, typename Inner, typename InnerBegFn, typename InnerEndFn, typename Cat>
00552 struct ByCategory {};
00553
00554 template <typename Outer, typename Inner, typename InnerBegFn, typename InnerEndFn>
00555 struct ByCategory<Outer, Inner, InnerBegFn, InnerEndFn, std::forward_iterator_tag> {
00556 typedef TwoLevelFwdIter<Outer, Inner, InnerBegFn, InnerEndFn> type;
00557 };
00558
00559 template <typename Outer, typename Inner, typename InnerBegFn, typename InnerEndFn>
00560 struct ByCategory<Outer, Inner, InnerBegFn, InnerEndFn, std::bidirectional_iterator_tag> {
00561 typedef TwoLevelBiDirIter<Outer, Inner, InnerBegFn, InnerEndFn> type;
00562 };
00563
00564 template <typename Outer, typename Inner, typename InnerBegFn, typename InnerEndFn>
00565 struct ByCategory<Outer, Inner, InnerBegFn, InnerEndFn, std::random_access_iterator_tag> {
00566 typedef TwoLevelRandIter<Outer, Inner, InnerBegFn, InnerEndFn> type;
00567 };
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 }
00598
00600 template <typename Outer, typename Inner, typename InnerBegFn, typename InnerEndFn>
00601 struct ChooseTwoLevelIterator {
00602 private:
00603
00604 typedef typename std::iterator_traits<Inner>::iterator_category CatInner;
00605
00606 public:
00607 typedef typename TwoLevelIteratorImpl::ByCategory<Outer, Inner, InnerBegFn, InnerEndFn, CatInner>::type type;
00608 };
00609
00611 template <typename Outer, typename InnerBegFn, typename InnerEndFn>
00612 typename ChooseTwoLevelIterator<Outer, typename InnerBegFn::result_type, InnerBegFn, InnerEndFn>::type
00613 make_two_level_begin (Outer beg, Outer end, InnerBegFn innerBegFn, InnerEndFn innerEndFn) {
00614 const bool V = std::is_same<typename InnerBegFn::result_type, typename InnerEndFn::result_type>::value;
00615 assert (V);
00616
00617 typedef typename InnerBegFn::result_type Inner;
00618 typedef typename ChooseTwoLevelIterator<Outer, Inner, InnerBegFn, InnerEndFn>::type Ret_ty;
00619
00620 return Ret_ty (beg, end, innerBegFn, innerEndFn);
00621 }
00622
00624 template <typename Outer, typename InnerBegFn, typename InnerEndFn>
00625 typename ChooseTwoLevelIterator<Outer, typename InnerBegFn::result_type, InnerBegFn, InnerEndFn>::type
00626 make_two_level_end (Outer beg, Outer end, InnerBegFn innerBegFn, InnerEndFn innerEndFn) {
00627 const bool V = std::is_same<typename InnerBegFn::result_type, typename InnerEndFn::result_type>::value;
00628 assert (V);
00629
00630 typedef typename InnerBegFn::result_type Inner;
00631 typedef typename ChooseTwoLevelIterator<Outer, Inner, InnerBegFn, InnerEndFn>::type Ret_ty;
00632
00633 return Ret_ty (end, end, innerBegFn, innerEndFn);
00634 }
00635
00636 namespace TwoLevelIteratorImpl {
00637 template <typename C>
00638 struct GetBegin: public std::unary_function<C&, typename C::iterator> {
00639 inline typename C::iterator operator () (C& c) const {
00640 return c.begin ();
00641 }
00642 };
00643
00644 template <typename C>
00645 struct GetEnd: public std::unary_function<C&, typename C::iterator> {
00646 inline typename C::iterator operator () (C& c) const {
00647 return c.end ();
00648 }
00649 };
00650
00651
00652 template <typename C>
00653 struct GetCbegin: public std::unary_function<const C&, typename C::const_iterator> {
00654 inline typename C::const_iterator operator () (const C& c) const {
00655 return c.begin ();
00656 }
00657 };
00658
00659 template <typename C>
00660 struct GetCend: public std::unary_function<const C&, typename C::const_iterator> {
00661 inline typename C::const_iterator operator () (const C& c) const {
00662 return c.end ();
00663 }
00664 };
00665
00666 template <typename C>
00667 struct GetRbegin: public std::unary_function<C&, typename C::reverse_iterator> {
00668 inline typename C::reverse_iterator operator () (C& c) const {
00669 return c.rbegin ();
00670 }
00671 };
00672
00673 template <typename C>
00674 struct GetRend: public std::unary_function<C&, typename C::reverse_iterator> {
00675 inline typename C::reverse_iterator operator () (C& c) const {
00676 return c.rend ();
00677 }
00678 };
00679
00680
00681 template <typename C>
00682 struct GetCRbegin: public std::unary_function<const C&, typename C::const_reverse_iterator> {
00683 inline typename C::const_reverse_iterator operator () (const C& c) const {
00684 return c.rbegin ();
00685 }
00686 };
00687
00688 template <typename C>
00689 struct GetCRend: public std::unary_function<const C&, typename C::const_reverse_iterator> {
00690 inline typename C::const_reverse_iterator operator () (const C& c) const {
00691 return c.rend ();
00692 }
00693 };
00694
00695 enum StlIterKind { NORMAL, CONST, REVERSE, CONST_REVERSE };
00696
00697 template <typename C, typename I> struct IsConstIter
00698 { static const bool value = false; };
00699
00700 template <typename C> struct IsConstIter<C, typename C::const_iterator>
00701 { static const bool value = true; };
00702
00703 template <typename C, typename I> struct IsRvrsIter
00704 { static const bool value = false; };
00705
00706 template <typename C> struct IsRvrsIter<C, typename C::reverse_iterator>
00707 { static const bool value = true; };
00708
00709 template <typename C, typename I> struct IsRvrsConstIter
00710 { static const bool value = false; };
00711
00712 template <typename C> struct IsRvrsConstIter<C, typename C::const_reverse_iterator>
00713 { static const bool value = true; };
00714
00715 template <typename C, typename I>
00716 struct GetStlIterKind {
00717 static const bool isRvrs = IsRvrsIter<C, I>::value || IsRvrsConstIter<C, I>::value;
00718 static const bool isConst = IsConstIter<C, I>::value || IsRvrsConstIter<C, I>::value;
00719
00720 static const StlIterKind value =
00721 isRvrs ? (isConst ? CONST_REVERSE: REVERSE)
00722 : (isConst ? CONST : NORMAL);
00723 };
00724
00725 template <typename C, typename I, enum StlIterKind>
00726 struct ChooseStlIter {
00727 typedef void Inner;
00728 };
00729
00730 template <typename C, typename I>
00731 struct ChooseStlIter<C, I, NORMAL> {
00732
00733 typedef typename C::iterator Inner;
00734 typedef GetBegin<C> InnerBegFn;
00735 typedef GetEnd<C> InnerEndFn;
00736
00737 };
00738
00739 template <typename C, typename I>
00740 struct ChooseStlIter<C, I, CONST> {
00741
00742 typedef typename C::const_iterator Inner;
00743 typedef GetCbegin<C> InnerBegFn;
00744 typedef GetCend<C> InnerEndFn;
00745 };
00746
00747 template <typename C, typename I>
00748 struct ChooseStlIter<C, I, REVERSE> {
00749
00750 typedef typename C::reverse_iterator Inner;
00751 typedef GetRbegin<C> InnerBegFn;
00752 typedef GetRend<C> InnerEndFn;
00753 };
00754
00755 template <typename C, typename I>
00756 struct ChooseStlIter<C, I, CONST_REVERSE> {
00757
00758 typedef typename C::const_reverse_iterator Inner;
00759 typedef GetCRbegin<C> InnerBegFn;
00760 typedef GetCRend<C> InnerEndFn;
00761 };
00762
00763 template <typename Outer, typename Inner>
00764 struct ChooseStlTwoLevelIterImpl {
00765
00766 typedef typename std::iterator_traits<Outer>::value_type C;
00767 static const TwoLevelIteratorImpl::StlIterKind KIND = TwoLevelIteratorImpl::GetStlIterKind<C, Inner>::value;
00768 typedef TwoLevelIteratorImpl::ChooseStlIter<C, Inner, KIND> CStl;
00769 typedef typename CStl::InnerBegFn InnerBegFn;
00770 typedef typename CStl::InnerEndFn InnerEndFn;
00771 typedef typename ChooseTwoLevelIterator<Outer, Inner, InnerBegFn, InnerEndFn>::type type;
00772
00773 static type make (Outer beg, Outer end) {
00774 return type (beg, end, InnerBegFn (), InnerEndFn ());
00775 }
00776 };
00777
00778 template <typename Outer> struct StlInnerIsIterator
00779 : public ChooseStlTwoLevelIterImpl<Outer, typename std::iterator_traits<Outer>::value_type::iterator> {};
00780
00781 template <typename Outer> struct StlInnerIsConstIterator
00782 : public ChooseStlTwoLevelIterImpl<Outer, typename std::iterator_traits<Outer>::value_type::const_iterator> {};
00783
00784 template <typename Outer> struct StlInnerIsRvrsIterator
00785 : public ChooseStlTwoLevelIterImpl<Outer, typename std::iterator_traits<Outer>::value_type::reverse_iterator> {};
00786
00787 template <typename Outer> struct StlInnerIsConstRvrsIterator
00788 : public ChooseStlTwoLevelIterImpl<Outer, typename std::iterator_traits<Outer>::value_type::const_reverse_iterator> {};
00789
00790 }
00791
00793 template <typename Outer, typename Inner>
00794 struct ChooseStlTwoLevelIterator {
00795 typedef typename TwoLevelIteratorImpl::ChooseStlTwoLevelIterImpl<Outer, Inner>::type type;
00796 };
00797
00798 template <typename Outer>
00799 typename TwoLevelIteratorImpl::StlInnerIsIterator<Outer>::type
00800 stl_two_level_begin (Outer beg, Outer end) {
00801 return TwoLevelIteratorImpl::StlInnerIsIterator<Outer>::make (beg, end);
00802 }
00803
00804 template <typename Outer>
00805 typename TwoLevelIteratorImpl::StlInnerIsIterator<Outer>::type
00806 stl_two_level_end (Outer beg, Outer end) {
00807 return TwoLevelIteratorImpl::StlInnerIsIterator<Outer>::make (end, end);
00808 }
00809
00810 template <typename Outer>
00811 typename TwoLevelIteratorImpl::StlInnerIsConstIterator<Outer>::type
00812 stl_two_level_cbegin (Outer beg, Outer end) {
00813 return TwoLevelIteratorImpl::StlInnerIsConstIterator<Outer>::make (beg, end);
00814 }
00815
00816 template <typename Outer>
00817 typename TwoLevelIteratorImpl::StlInnerIsConstIterator<Outer>::type
00818 stl_two_level_cend (Outer beg, Outer end) {
00819 return TwoLevelIteratorImpl::StlInnerIsConstIterator<Outer>::make (end, end);
00820 }
00821
00822 template <typename Outer>
00823 typename TwoLevelIteratorImpl::StlInnerIsRvrsIterator<Outer>::type
00824 stl_two_level_rbegin (Outer beg, Outer end) {
00825 return TwoLevelIteratorImpl::StlInnerIsRvrsIterator<Outer>::make (beg, end);
00826 }
00827
00828 template <typename Outer>
00829 typename TwoLevelIteratorImpl::StlInnerIsRvrsIterator<Outer>::type
00830 stl_two_level_rend (Outer beg, Outer end) {
00831 return TwoLevelIteratorImpl::StlInnerIsRvrsIterator<Outer>::make (end, end);
00832 }
00833
00834 template <typename Outer>
00835 typename TwoLevelIteratorImpl::StlInnerIsConstRvrsIterator<Outer>::type
00836 stl_two_level_crbegin (Outer beg, Outer end) {
00837 return TwoLevelIteratorImpl::StlInnerIsConstRvrsIterator<Outer>::make (beg, end);
00838 }
00839
00840 template <typename Outer>
00841 typename TwoLevelIteratorImpl::StlInnerIsConstRvrsIterator<Outer>::type
00842 stl_two_level_crend (Outer beg, Outer end) {
00843 return TwoLevelIteratorImpl::StlInnerIsConstRvrsIterator<Outer>::make (end, end);
00844 }
00845
00846
00847 }
00848
00849 #endif // GALOIS_TWO_LEVEL_ITER_H