lltreeiterators.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:27k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /**
  2.  * @file   lltreeiterators.h
  3.  * @author Nat Goodspeed
  4.  * @date   2008-08-19
  5.  * @brief  This file defines iterators useful for traversing arbitrary node
  6.  *         classes, potentially polymorphic, linked into strict tree
  7.  *         structures.
  8.  *
  9.  *         Dereferencing any one of these iterators actually yields a @em
  10.  *         pointer to the node in question. For example, given an
  11.  *         LLLinkedIter<MyNode> <tt>li</tt>, <tt>*li</tt> gets you a pointer
  12.  *         to MyNode, and <tt>**li</tt> gets you the MyNode instance itself.
  13.  *         More commonly, instead of writing <tt>li->member</tt>, you write
  14.  *         <tt>(*li)->member</tt> -- as you would if you were traversing an
  15.  *         STL container of MyNode pointers.
  16.  *
  17.  *         It would certainly be possible to build these iterators so that
  18.  *         <tt>*iterator</tt> would return a reference to the node itself
  19.  *         rather than a pointer to the node, and for many purposes it would
  20.  *         even be more convenient. However, that would be insufficiently
  21.  *         flexible. If you want to use an iterator range to (e.g.) initialize
  22.  *         a std::vector collecting results -- you rarely want to actually @em
  23.  *         copy the nodes in question. You're much more likely to want to copy
  24.  *         <i>pointers to</i> the traversed nodes. Hence these iterators
  25.  *         produce pointers.
  26.  *
  27.  *         Though you specify the actual NODE class as the template parameter,
  28.  *         these iterators internally use LLPtrTo<> to discover whether to
  29.  *         store and return an LLPointer<NODE> or a simple NODE*.
  30.  *
  31.  *         By strict tree structures, we mean that each child must have
  32.  *         exactly one parent. This forbids a child claiming any ancestor as a
  33.  *         child of its own. Child nodes with multiple parents will be visited
  34.  *         once for each parent. Cycles in the graph will result in either an
  35.  *         infinite loop or an out-of-memory crash. You Have Been Warned.
  36.  * 
  37.  * $LicenseInfo:firstyear=2008&license=viewergpl$
  38.  * 
  39.  * Copyright (c) 2008-2010, Linden Research, Inc.
  40.  * 
  41.  * Second Life Viewer Source Code
  42.  * The source code in this file ("Source Code") is provided by Linden Lab
  43.  * to you under the terms of the GNU General Public License, version 2.0
  44.  * ("GPL"), unless you have obtained a separate licensing agreement
  45.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  46.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  47.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  48.  * 
  49.  * There are special exceptions to the terms and conditions of the GPL as
  50.  * it is applied to this Source Code. View the full text of the exception
  51.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  52.  * online at
  53.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  54.  * 
  55.  * By copying, modifying or distributing this software, you acknowledge
  56.  * that you have read and understood your obligations described above,
  57.  * and agree to abide by those obligations.
  58.  * 
  59.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  60.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  61.  * COMPLETENESS OR PERFORMANCE.
  62.  * $/LicenseInfo$
  63.  */
  64. #if ! defined(LL_LLTREEITERATORS_H)
  65. #define LL_LLTREEITERATORS_H
  66. #include "llptrto.h"
  67. #include <vector>
  68. #include <deque>
  69. #include <boost/iterator/iterator_facade.hpp>
  70. #include <boost/function.hpp>
  71. #include <boost/static_assert.hpp>
  72. namespace LLTreeIter
  73. {
  74.     /// Discriminator between LLTreeUpIter and LLTreeDownIter
  75.     enum RootIter { UP, DOWN };
  76.     /// Discriminator between LLTreeDFSIter, LLTreeDFSPostIter and LLTreeBFSIter
  77.     enum WalkIter { DFS_PRE, DFS_POST, BFS };
  78. }
  79. /**
  80.  * LLBaseIter defines some machinery common to all these iterators. We use
  81.  * boost::iterator_facade to define the iterator boilerplate: the conventional
  82.  * operators and methods necessary to implement a standards-conforming
  83.  * iterator. That allows us to specify the actual iterator semantics in terms
  84.  * of equal(), dereference() and increment() methods.
  85.  */
  86. template <class SELFTYPE, class NODE>
  87. class LLBaseIter: public boost::iterator_facade<SELFTYPE,
  88.                                                 // use pointer type as the
  89.                                                 // reference type
  90.                                                 typename LLPtrTo<NODE>::type,
  91.                                                 boost::forward_traversal_tag>
  92. {
  93. protected:
  94.     /// LLPtrTo<NODE>::type is either NODE* or LLPointer<NODE>, as appropriate
  95.     typedef typename LLPtrTo<NODE>::type ptr_type;
  96.     /// function that advances from this node to next accepts a node pointer
  97.     /// and returns another
  98.     typedef boost::function<ptr_type(const ptr_type&)> func_type;
  99.     typedef SELFTYPE self_type;
  100. };
  101. /// Functor returning NULL, suitable for an end-iterator's 'next' functor
  102. template <class NODE>
  103. typename LLPtrTo<NODE>::type LLNullNextFunctor(const typename LLPtrTo<NODE>::type&)
  104. {
  105.     return typename LLPtrTo<NODE>::type();
  106. }
  107. /**
  108.  * LLLinkedIter is an iterator over an intrusive singly-linked list. The
  109.  * beginning of the list is represented by LLLinkedIter(list head); the end is
  110.  * represented by LLLinkedIter().
  111.  *
  112.  * The begin LLLinkedIter must be instantiated with a functor to extract the
  113.  * 'next' pointer from the current node. Supposing that the link pointer is @c
  114.  * public, something like:
  115.  *
  116.  * @code
  117.  * NODE* mNext;
  118.  * @endcode
  119.  *
  120.  * you can use (e.g.) <tt>boost::bind(&NODE::mNext, _1)</tt> for the purpose.
  121.  * Alternatively, you can bind whatever accessor method is normally used to
  122.  * advance to the next node, e.g. for:
  123.  *
  124.  * @code
  125.  * NODE* next() const;
  126.  * @endcode
  127.  *
  128.  * you can use <tt>boost::bind(&NODE::next, _1)</tt>.
  129.  */
  130. template <class NODE>
  131. class LLLinkedIter: public LLBaseIter<LLLinkedIter<NODE>, NODE>
  132. {
  133.     typedef LLBaseIter<LLLinkedIter<NODE>, NODE> super;
  134. protected:
  135.     /// some methods need to return a reference to self
  136.     typedef typename super::self_type self_type;
  137.     typedef typename super::ptr_type ptr_type;
  138.     typedef typename super::func_type func_type;
  139. public:
  140.     /// Instantiate an LLLinkedIter to start a range, or to end a range before
  141.     /// a particular list entry. Pass a functor to extract the 'next' pointer
  142.     /// from the current node.
  143.     LLLinkedIter(const ptr_type& entry, const func_type& nextfunc):
  144.         mCurrent(entry),
  145.         mNextFunc(nextfunc)
  146.     {}
  147.     /// Instantiate an LLLinkedIter to end a range at the end of the list
  148.     LLLinkedIter():
  149.         mCurrent(),
  150.         mNextFunc(LLNullNextFunctor<NODE>)
  151.     {}
  152. private:
  153.     /// leverage boost::iterator_facade
  154.     friend class boost::iterator_core_access;
  155.     /// advance
  156.     void increment()
  157.     {
  158.         mCurrent = mNextFunc(mCurrent);
  159.     }
  160.     /// equality
  161.     bool equal(const self_type& that) const { return this->mCurrent == that.mCurrent; }
  162.     /// dereference
  163.     ptr_type& dereference() const { return const_cast<ptr_type&>(mCurrent); }
  164.     ptr_type mCurrent;
  165.     func_type mNextFunc;
  166. };
  167. /**
  168.  * LLTreeUpIter walks from the node in hand to the root of the tree. The term
  169.  * "up" is applied to a tree visualized with the root at the top.
  170.  *
  171.  * LLTreeUpIter is an alias for LLLinkedIter, since any linked tree that you
  172.  * can navigate that way at all contains parent pointers.
  173.  */
  174. template <class NODE>
  175. class LLTreeUpIter: public LLLinkedIter<NODE>
  176. {
  177.     typedef LLLinkedIter<NODE> super;
  178. public:
  179.     /// Instantiate an LLTreeUpIter to start from a particular tree node, or
  180.     /// to end a parent traversal before reaching a particular ancestor. Pass
  181.     /// a functor to extract the 'parent' pointer from the current node.
  182.     LLTreeUpIter(const typename super::ptr_type& node,
  183.                  const typename super::func_type& parentfunc):
  184.         super(node, parentfunc)
  185.     {}
  186.     /// Instantiate an LLTreeUpIter to end a range at the root of the tree
  187.     LLTreeUpIter():
  188.         super()
  189.     {}
  190. };
  191. /**
  192.  * LLTreeDownIter walks from the root of the tree to the node in hand. The
  193.  * term "down" is applied to a tree visualized with the root at the top.
  194.  *
  195.  * Though you instantiate the begin() LLTreeDownIter with a pointer to some
  196.  * node at an arbitrary location in the tree, the root will be the first node
  197.  * you dereference and the passed node will be the last node you dereference.
  198.  *
  199.  * On construction, LLTreeDownIter walks from the current node to the root,
  200.  * capturing the path. Then in use, it replays that walk in reverse. As with
  201.  * all traversals of interesting data structures, it is actively dangerous to
  202.  * modify the tree during an LLTreeDownIter walk.
  203.  */
  204. template <class NODE>
  205. class LLTreeDownIter: public LLBaseIter<LLTreeDownIter<NODE>, NODE>
  206. {
  207.     typedef LLBaseIter<LLTreeDownIter<NODE>, NODE> super;
  208.     typedef typename super::self_type self_type;
  209. protected:
  210.     typedef typename super::ptr_type ptr_type;
  211.     typedef typename super::func_type func_type;
  212. private:
  213.     typedef std::vector<ptr_type> list_type;
  214. public:
  215.     /// Instantiate an LLTreeDownIter to end at a particular tree node. Pass a
  216.     /// functor to extract the 'parent' pointer from the current node.
  217.     LLTreeDownIter(const ptr_type& node,
  218.                    const func_type& parentfunc)
  219.     {
  220.         for (ptr_type n = node; n; n = parentfunc(n))
  221.             mParents.push_back(n);
  222.     }
  223.     /// Instantiate an LLTreeDownIter representing "here", the end of the loop
  224.     LLTreeDownIter() {}
  225. private:
  226.     /// leverage boost::iterator_facade
  227.     friend class boost::iterator_core_access;
  228.     /// advance
  229.     void increment()
  230.     {
  231.         mParents.pop_back();
  232.     }
  233.     /// equality
  234.     bool equal(const self_type& that) const { return this->mParents == that.mParents; }
  235.     /// implement dereference/indirection operators
  236.     ptr_type& dereference() const { return const_cast<ptr_type&>(mParents.back()); }
  237.     list_type mParents;
  238. };
  239. /**
  240.  * When you want to select between LLTreeUpIter and LLTreeDownIter with a
  241.  * compile-time discriminator, use LLTreeRootIter with an LLTreeIter::RootIter
  242.  * template arg.
  243.  */
  244. template <LLTreeIter::RootIter DISCRIM, class NODE>
  245. class LLTreeRootIter
  246. {
  247.     enum { use_a_valid_LLTreeIter_RootIter_value = false };
  248. public:
  249.     /// Bogus constructors for default (unrecognized discriminator) case
  250.     template <typename TYPE1, typename TYPE2>
  251.     LLTreeRootIter(TYPE1, TYPE2)
  252.     {
  253.         BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_RootIter_value);
  254.     }
  255.     LLTreeRootIter()
  256.     {
  257.         BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_RootIter_value);
  258.     }
  259. };
  260. /// Specialize for LLTreeIter::UP
  261. template <class NODE>
  262. class LLTreeRootIter<LLTreeIter::UP, NODE>: public LLTreeUpIter<NODE>
  263. {
  264.     typedef LLTreeUpIter<NODE> super;
  265. public:
  266.     /// forward begin ctor
  267.     LLTreeRootIter(const typename super::ptr_type& node,
  268.                    const typename super::func_type& parentfunc):
  269.         super(node, parentfunc)
  270.     {}
  271.     /// forward end ctor
  272.     LLTreeRootIter():
  273.         super()
  274.     {}
  275. };
  276. /// Specialize for LLTreeIter::DOWN
  277. template <class NODE>
  278. class LLTreeRootIter<LLTreeIter::DOWN, NODE>: public LLTreeDownIter<NODE>
  279. {
  280.     typedef LLTreeDownIter<NODE> super;
  281. public:
  282.     /// forward begin ctor
  283.     LLTreeRootIter(const typename super::ptr_type& node,
  284.                    const typename super::func_type& parentfunc):
  285.         super(node, parentfunc)
  286.     {}
  287.     /// forward end ctor
  288.     LLTreeRootIter():
  289.         super()
  290.     {}
  291. };
  292. /**
  293.  * Instantiated with a tree node, typically the root, LLTreeDFSIter "flattens"
  294.  * a depth-first tree walk through that node and all its descendants.
  295.  *
  296.  * The begin() LLTreeDFSIter must be instantiated with functors to obtain from
  297.  * a given node begin() and end() iterators for that node's children. For this
  298.  * reason, you must specify the type of the node's child iterator as an
  299.  * additional template parameter.
  300.  *
  301.  * Specifically, the begin functor must return an iterator whose dereferenced
  302.  * value is a @em pointer to a child tree node. For instance, if each node
  303.  * tracks its children in an STL container of node* pointers, you can simply
  304.  * return that container's begin() iterator.
  305.  *
  306.  * Alternatively, if a node tracks its children with a classic linked list,
  307.  * write a functor returning LLLinkedIter<NODE>.
  308.  *
  309.  * The end() LLTreeDFSIter must, of course, match the begin() iterator's
  310.  * template parameters, but is constructed without runtime parameters.
  311.  */
  312. template <class NODE, typename CHILDITER>
  313. class LLTreeDFSIter: public LLBaseIter<LLTreeDFSIter<NODE, CHILDITER>, NODE>
  314. {
  315.     typedef LLBaseIter<LLTreeDFSIter<NODE, CHILDITER>, NODE> super;
  316.     typedef typename super::self_type self_type;
  317. protected:
  318.     typedef typename super::ptr_type ptr_type;
  319.     // The func_type is different for this: from a NODE pointer, we must
  320.     // obtain a CHILDITER.
  321.     typedef boost::function<CHILDITER(const ptr_type&)> func_type;
  322. private:
  323.     typedef std::vector<ptr_type> list_type;
  324. public:
  325.     /// Instantiate an LLTreeDFSIter to start a depth-first walk. Pass
  326.     /// functors to extract the 'child begin' and 'child end' iterators from
  327.     /// each node.
  328.     LLTreeDFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc)
  329.     : mBeginFunc(beginfunc),
  330.     mEndFunc(endfunc),
  331.     mSkipChildren(false)
  332.     {
  333.         // Only push back this node if it's non-NULL!
  334.         if (node)
  335.             mPending.push_back(node);
  336.     }
  337.     /// Instantiate an LLTreeDFSIter to mark the end of the walk
  338.     LLTreeDFSIter() : mSkipChildren(false) {}
  339.     /// flags iterator logic to skip traversing children of current node on next increment
  340.     void skipDescendants(bool skip = true) { mSkipChildren = skip; }
  341. private:
  342.     /// leverage boost::iterator_facade
  343.     friend class boost::iterator_core_access;
  344.     /// advance
  345.     /// This implementation is due to http://en.wikipedia.org/wiki/Depth-first_search
  346.     void increment()
  347.     {
  348.         // Capture the node we were just looking at
  349.         ptr_type current = mPending.back();
  350.         // Remove it from mPending so we don't process it again later
  351.         mPending.pop_back();
  352. if (!mSkipChildren)
  353. {
  354. // Add all its children to mPending
  355. addChildren(current);
  356. }
  357. // reset flag after each step
  358. mSkipChildren = false;
  359.     }
  360.     /// equality
  361.     bool equal(const self_type& that) const { return this->mPending == that.mPending; }
  362.     /// implement dereference/indirection operators
  363.     ptr_type& dereference() const { return const_cast<ptr_type&>(mPending.back()); }
  364.     /// Add the direct children of the specified node to mPending
  365.     void addChildren(const ptr_type& node)
  366.     {
  367.         // If we just use push_back() for each child in turn, we'll end up
  368.         // processing children in reverse order. We don't want to assume
  369.         // CHILDITER is reversible: some of the linked trees we'll be
  370.         // processing manage their children using singly-linked lists. So
  371.         // figure out how many children there are, grow mPending by that size
  372.         // and reverse-copy the children into the new space.
  373.         CHILDITER chi = mBeginFunc(node), chend = mEndFunc(node);
  374.         // grow mPending by the number of children
  375.         mPending.resize(mPending.size() + std::distance(chi, chend));
  376.         // reverse-copy the children into the newly-expanded space
  377.         std::copy(chi, chend, mPending.rbegin());
  378.     }
  379.     /// list of the nodes yet to be processed
  380.     list_type mPending;
  381.     /// functor to extract begin() child iterator
  382.     func_type mBeginFunc;
  383.     /// functor to extract end() child iterator
  384.     func_type mEndFunc;
  385.     /// flag which controls traversal of children (skip children of current node if true)
  386.     bool mSkipChildren;
  387. };
  388. /**
  389.  * Instantiated with a tree node, typically the root, LLTreeDFSPostIter
  390.  * "flattens" a depth-first tree walk through that node and all its
  391.  * descendants. Whereas LLTreeDFSIter visits each node before visiting any of
  392.  * its children, LLTreeDFSPostIter visits all of a node's children before
  393.  * visiting the node itself.
  394.  *
  395.  * The begin() LLTreeDFSPostIter must be instantiated with functors to obtain
  396.  * from a given node begin() and end() iterators for that node's children. For
  397.  * this reason, you must specify the type of the node's child iterator as an
  398.  * additional template parameter.
  399.  *
  400.  * Specifically, the begin functor must return an iterator whose dereferenced
  401.  * value is a @em pointer to a child tree node. For instance, if each node
  402.  * tracks its children in an STL container of node* pointers, you can simply
  403.  * return that container's begin() iterator.
  404.  *
  405.  * Alternatively, if a node tracks its children with a classic linked list,
  406.  * write a functor returning LLLinkedIter<NODE>.
  407.  *
  408.  * The end() LLTreeDFSPostIter must, of course, match the begin() iterator's
  409.  * template parameters, but is constructed without runtime parameters.
  410.  */
  411. template <class NODE, typename CHILDITER>
  412. class LLTreeDFSPostIter: public LLBaseIter<LLTreeDFSPostIter<NODE, CHILDITER>, NODE>
  413. {
  414.     typedef LLBaseIter<LLTreeDFSPostIter<NODE, CHILDITER>, NODE> super;
  415.     typedef typename super::self_type self_type;
  416. protected:
  417.     typedef typename super::ptr_type ptr_type;
  418.     // The func_type is different for this: from a NODE pointer, we must
  419.     // obtain a CHILDITER.
  420.     typedef boost::function<CHILDITER(const ptr_type&)> func_type;
  421. private:
  422.     // Upon reaching a given node in our pending list, we need to know whether
  423.     // we've already pushed that node's children, so we must associate a bool
  424.     // with each node pointer.
  425.     typedef std::vector< std::pair<ptr_type, bool> > list_type;
  426. public:
  427.     /// Instantiate an LLTreeDFSPostIter to start a depth-first walk. Pass
  428.     /// functors to extract the 'child begin' and 'child end' iterators from
  429.     /// each node.
  430.     LLTreeDFSPostIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc)
  431.     : mBeginFunc(beginfunc),
  432.     mEndFunc(endfunc),
  433.     mSkipAncestors(false)
  434.     {
  435.         if (! node)
  436.             return;
  437.         mPending.push_back(typename list_type::value_type(node, false));
  438.         makeCurrent();
  439.     }
  440.     /// Instantiate an LLTreeDFSPostIter to mark the end of the walk
  441.     LLTreeDFSPostIter() : mSkipAncestors(false) {}
  442.     /// flags iterator logic to skip traversing ancestors of current node on next increment
  443.     void skipAncestors(bool skip = true) { mSkipAncestors = skip; }
  444. private:
  445.     /// leverage boost::iterator_facade
  446.     friend class boost::iterator_core_access;
  447.     /// advance
  448.     /// This implementation is due to http://en.wikipedia.org/wiki/Depth-first_search
  449.     void increment()
  450.     {
  451.         // Pop the previous current node
  452.         mPending.pop_back();
  453.         makeCurrent();
  454.     }
  455.     /// equality
  456.     bool equal(const self_type& that) const { return this->mPending == that.mPending; }
  457.     /// implement dereference/indirection operators
  458.     ptr_type& dereference() const { return const_cast<ptr_type&>(mPending.back().first); }
  459. struct isOpen
  460. {
  461. bool operator()(const typename list_type::value_type& item)
  462. {
  463. return item.second;
  464. }
  465. };
  466.     /// Call this each time we change mPending.back() -- that is, every time
  467.     /// we're about to change the value returned by dereference(). If we
  468.     /// haven't yet pushed the new node's children, do so now.
  469.     void makeCurrent()
  470.     {
  471. if (mSkipAncestors)
  472. {
  473. mPending.erase(std::remove_if(mPending.begin(), mPending.end(), isOpen()), mPending.end());
  474. mSkipAncestors = false;
  475. }
  476.         // Once we've popped the last node, this becomes a no-op.
  477.         if (mPending.empty())
  478.             return;
  479.         // Here mPending.back() holds the node pointer we're proposing to
  480.         // dereference next. Have we pushed that node's children yet?
  481.         if (mPending.back().second)
  482.             return;                 // if so, it's okay to visit this node now
  483.         // We haven't yet pushed this node's children. Do so now. Remember
  484.         // that we did -- while the node in question is still back().
  485.         mPending.back().second = true;
  486.         addChildren(mPending.back().first);
  487.         // Now, because we've just changed mPending.back(), make that new node
  488.         // current.
  489.         makeCurrent();
  490.     }
  491.     /// Add the direct children of the specified node to mPending
  492.     void addChildren(const ptr_type& node)
  493.     {
  494.         // If we just use push_back() for each child in turn, we'll end up
  495.         // processing children in reverse order. We don't want to assume
  496.         // CHILDITER is reversible: some of the linked trees we'll be
  497.         // processing manage their children using singly-linked lists. So
  498.         // figure out how many children there are, grow mPending by that size
  499.         // and reverse-copy the children into the new space.
  500.         CHILDITER chi = mBeginFunc(node), chend = mEndFunc(node);
  501.         // grow mPending by the number of children
  502.         mPending.resize(mPending.size() + std::distance(chi, chend));
  503.         // Reverse-copy the children into the newly-expanded space. We can't
  504.         // just use std::copy() because the source is a ptr_type, whereas the
  505.         // dest is a pair of (ptr_type, bool).
  506.         for (typename list_type::reverse_iterator pi = mPending.rbegin(); chi != chend; ++chi, ++pi)
  507.         {
  508.             pi->first = *chi;       // copy the child pointer
  509.             pi->second = false;     // we haven't yet pushed this child's chldren
  510.         }
  511.     }
  512.     /// list of the nodes yet to be processed
  513.     list_type mPending;
  514.     /// functor to extract begin() child iterator
  515.     func_type mBeginFunc;
  516.     /// functor to extract end() child iterator
  517.     func_type mEndFunc;
  518. /// flags logic to skip traversal of ancestors of current node
  519. bool mSkipAncestors;
  520. };
  521. /**
  522.  * Instantiated with a tree node, typically the root, LLTreeBFSIter "flattens"
  523.  * a breadth-first tree walk through that node and all its descendants.
  524.  *
  525.  * The begin() LLTreeBFSIter must be instantiated with functors to obtain from
  526.  * a given node the begin() and end() iterators of that node's children. For
  527.  * this reason, you must specify the type of the node's child iterator as an
  528.  * additional template parameter.
  529.  *
  530.  * Specifically, the begin functor must return an iterator whose dereferenced
  531.  * value is a @em pointer to a child tree node. For instance, if each node
  532.  * tracks its children in an STL container of node* pointers, you can simply
  533.  * return that container's begin() iterator.
  534.  *
  535.  * Alternatively, if a node tracks its children with a classic linked list,
  536.  * write a functor returning LLLinkedIter<NODE>.
  537.  *
  538.  * The end() LLTreeBFSIter must, of course, match the begin() iterator's
  539.  * template parameters, but is constructed without runtime parameters.
  540.  */
  541. template <class NODE, typename CHILDITER>
  542. class LLTreeBFSIter: public LLBaseIter<LLTreeBFSIter<NODE, CHILDITER>, NODE>
  543. {
  544.     typedef LLBaseIter<LLTreeBFSIter<NODE, CHILDITER>, NODE> super;
  545.     typedef typename super::self_type self_type;
  546. protected:
  547.     typedef typename super::ptr_type ptr_type;
  548.     // The func_type is different for this: from a NODE pointer, we must
  549.     // obtain a CHILDITER.
  550.     typedef boost::function<CHILDITER(const ptr_type&)> func_type;
  551. private:
  552.     // We need a FIFO queue rather than a LIFO stack. Use a deque rather than
  553.     // a vector, since vector can't implement pop_front() efficiently.
  554.     typedef std::deque<ptr_type> list_type;
  555. public:
  556.     /// Instantiate an LLTreeBFSIter to start a depth-first walk. Pass
  557.     /// functors to extract the 'child begin' and 'child end' iterators from
  558.     /// each node.
  559.     LLTreeBFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc):
  560.         mBeginFunc(beginfunc),
  561.         mEndFunc(endfunc)
  562.     {
  563.         if (node)
  564.             mPending.push_back(node);
  565.     }
  566.     /// Instantiate an LLTreeBFSIter to mark the end of the walk
  567.     LLTreeBFSIter() {}
  568. private:
  569.     /// leverage boost::iterator_facade
  570.     friend class boost::iterator_core_access;
  571.     /// advance
  572.     /// This implementation is due to http://en.wikipedia.org/wiki/Breadth-first_search
  573.     void increment()
  574.     {
  575.         // Capture the node we were just looking at
  576.         ptr_type current = mPending.front();
  577.         // Remove it from mPending so we don't process it again later
  578.         mPending.pop_front();
  579.         // Add all its children to mPending
  580.         CHILDITER chend = mEndFunc(current);
  581.         for (CHILDITER chi = mBeginFunc(current); chi != chend; ++chi)
  582.             mPending.push_back(*chi);
  583.     }
  584.     /// equality
  585.     bool equal(const self_type& that) const { return this->mPending == that.mPending; }
  586.     /// implement dereference/indirection operators
  587.     ptr_type& dereference() const { return const_cast<ptr_type&>(mPending.front()); }
  588.     /// list of the nodes yet to be processed
  589.     list_type mPending;
  590.     /// functor to extract begin() child iterator
  591.     func_type mBeginFunc;
  592.     /// functor to extract end() child iterator
  593.     func_type mEndFunc;
  594. };
  595. /**
  596.  * When you want to select between LLTreeDFSIter, LLTreeDFSPostIter and
  597.  * LLTreeBFSIter with a compile-time discriminator, use LLTreeWalkIter with an
  598.  * LLTreeIter::WalkIter template arg.
  599.  */
  600. template <LLTreeIter::WalkIter DISCRIM, class NODE, typename CHILDITER>
  601. class LLTreeWalkIter
  602. {
  603.     enum { use_a_valid_LLTreeIter_WalkIter_value = false };
  604. public:
  605.     /// Bogus constructors for default (unrecognized discriminator) case
  606.     template <typename TYPE1, typename TYPE2>
  607.     LLTreeWalkIter(TYPE1, TYPE2)
  608.     {
  609.         BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_WalkIter_value);
  610.     }
  611.     LLTreeWalkIter()
  612.     {
  613.         BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_WalkIter_value);
  614.     }
  615. };
  616. /// Specialize for LLTreeIter::DFS_PRE
  617. template <class NODE, typename CHILDITER>
  618. class LLTreeWalkIter<LLTreeIter::DFS_PRE, NODE, CHILDITER>:
  619.     public LLTreeDFSIter<NODE, CHILDITER>
  620. {
  621.     typedef LLTreeDFSIter<NODE, CHILDITER> super;
  622. public:
  623.     /// forward begin ctor
  624.     LLTreeWalkIter(const typename super::ptr_type& node,
  625.                    const typename super::func_type& beginfunc,
  626.                    const typename super::func_type& endfunc):
  627.         super(node, beginfunc, endfunc)
  628.     {}
  629.     /// forward end ctor
  630.     LLTreeWalkIter():
  631.         super()
  632.     {}
  633. };
  634. /// Specialize for LLTreeIter::DFS_POST
  635. template <class NODE, typename CHILDITER>
  636. class LLTreeWalkIter<LLTreeIter::DFS_POST, NODE, CHILDITER>:
  637.     public LLTreeDFSPostIter<NODE, CHILDITER>
  638. {
  639.     typedef LLTreeDFSPostIter<NODE, CHILDITER> super;
  640. public:
  641.     /// forward begin ctor
  642.     LLTreeWalkIter(const typename super::ptr_type& node,
  643.                    const typename super::func_type& beginfunc,
  644.                    const typename super::func_type& endfunc):
  645.         super(node, beginfunc, endfunc)
  646.     {}
  647.     /// forward end ctor
  648.     LLTreeWalkIter():
  649.         super()
  650.     {}
  651. };
  652. /// Specialize for LLTreeIter::BFS
  653. template <class NODE, typename CHILDITER>
  654. class LLTreeWalkIter<LLTreeIter::BFS, NODE, CHILDITER>:
  655.     public LLTreeBFSIter<NODE, CHILDITER>
  656. {
  657.     typedef LLTreeBFSIter<NODE, CHILDITER> super;
  658. public:
  659.     /// forward begin ctor
  660.     LLTreeWalkIter(const typename super::ptr_type& node,
  661.                    const typename super::func_type& beginfunc,
  662.                    const typename super::func_type& endfunc):
  663.         super(node, beginfunc, endfunc)
  664.     {}
  665.     /// forward end ctor
  666.     LLTreeWalkIter():
  667.         super()
  668.     {}
  669. };
  670. #endif /* ! defined(LL_LLTREEITERATORS_H) */