EvolvingObjects
parse_tree.h
00001 #ifndef PARSE_TREE_HH
00002 #define PARSE_TREE_HH
00003 
00168 #include <vector>
00169 #include <utility> // for swap
00170 
00171 #ifdef _MSC_VER
00172 #pragma warning(disable : 4786) // disable this nagging warning about the limitations of the mirkosoft debugger
00173 #endif
00174 
00175 namespace gp_parse_tree
00176 {
00177 
00178 #include "node_pool.h"
00179 
00181 template <class T>
00182 inline void do_the_swap(T& a, T& b)
00183 {
00184   T tmp = a;
00185   a = b;
00186   b = tmp;
00187 }
00188 
00189 template <class T> class parse_tree
00190 {
00191   public :
00192 
00193 
00194 class subtree
00195 {
00196 
00202 #if (defined(__GNUC__) || defined(_MSC_VER)) && !(defined(_MT) || defined(MACOSX) || defined(__APPLE__)) // not multithreaded (or MACOSX - J. Eggermont)
00203     Node_alloc<T>         node_allocator;
00204     Tree_alloc<subtree>   tree_allocator;
00205 #else
00206     Standard_Node_alloc<T>    node_allocator;
00207     Standard_alloc<subtree>   tree_allocator;
00208 #endif
00209 
00210 public :
00211 
00212     typedef subtree* iterator;
00213     typedef const subtree* const_iterator;
00214 
00215         /* Constructors, assignments */
00216 
00217     subtree(void) : content(node_allocator.allocate()), args(0), parent(0), _cumulative_size(0), _depth(0), _size(1)
00218                         {}
00219     subtree(const subtree& s)
00220         : content(node_allocator.allocate()),
00221           args(0),
00222           parent(0),
00223           _cumulative_size(1),
00224           _depth(1),
00225           _size(1)
00226     {
00227         copy(s);
00228     }
00229 
00230     subtree(const T& t) : content(node_allocator.allocate()), args(0), parent(0), _cumulative_size(0), _depth(0), _size(1)
00231                         { copy(t); }
00232 
00233     template <class It>
00234         subtree(It b, It e) : content(node_allocator.allocate()), args(0), parent(0), _cumulative_size(0), _depth(0), _size(1)
00235     { // initialize in prefix order for efficiency reasons
00236         init(b, --e);
00237     }
00238 
00239     virtual ~subtree(void)    { tree_allocator.deallocate(args, arity()); node_allocator.deallocate(content); }
00240 
00241     subtree& operator=(const subtree& s)
00242         {
00243             if (s.get_root() == get_root())
00244         { // from the same tree, maybe a child. Don't take any chances
00245             subtree anotherS = s;
00246             return copy(anotherS);
00247         }
00248 
00249                 copy(s);
00250         updateAfterInsert();
00251         return *this;
00252         }
00253 
00254     subtree& operator=(const T& t)       { copy(t); updateAfterInsert(); return *this; }
00255 
00256         /* Access to the nodes */
00257 
00258     T&       operator*(void)             { return *content; }
00259     const T& operator*(void) const       { return *content; }
00260     T*       operator->(void)            { return content; }
00261     const T* operator->(void) const      { return content; }
00262 
00263         /* Equality, inequality check, Node needs to implement operator== */
00264 
00265         bool operator==(const subtree& other) const
00266         {
00267                 if (! (*content == *other.content))
00268                         return false;
00269 
00270                 for (int i = 0; i < arity(); i++)
00271                 {
00272                         if (!(args[i] == other.args[i]))
00273                                 return false;
00274                 }
00275 
00276                 return true;
00277         }
00278 
00279         bool operator !=(const subtree& other) const
00280         {
00281                 return !operator==(other);
00282         }
00283 
00284         /* Arity */
00285     int arity(void) const                { return content->arity(); }
00286 
00287         /* Evaluation with an increasing amount of user defined arguments */
00288         template <class RetVal>
00289         void apply(RetVal& v) const                              { (*content)(v, begin()); }
00290 
00291         template <class RetVal, class It>
00292         void apply(RetVal& v, It values) const
00293     {
00294         (*content)(v, begin(), values);
00295     }
00296 
00297     template <class RetVal, class It>
00298     void apply_mem_func(RetVal& v, It misc, void (T::* f)(RetVal&, typename subtree::iterator, It))
00299     {
00300         (content->*f)(v, begin(), misc);
00301     }
00302 
00303 
00304 /*      template <class RetVal, class It, class It2>
00305         void apply(RetVal& v, It values, It2 moreValues) const
00306                 { (*content)(v, begin(), values, moreValues); }
00307 
00308         template <class RetVal, class It, class It2, class It3>
00309         void apply(RetVal& v, It values, It2 moreValues, It3 evenMoreValues) const
00310                 { (*content)(v, begin(), values, moreValues, evenMoreValues); }
00311 */
00312 
00313     template <class Pred>
00314     void find_nodes(std::vector<subtree*>& result, Pred& p)
00315     {
00316         if (p(*content))
00317         {
00318             result.push_back(this);
00319         }
00320 
00321         for (int i = 0; i < arity(); ++i)
00322         {
00323             args[i].find_nodes(result, p);
00324         }
00325     }
00326 
00327     template <class Pred>
00328     void find_nodes(std::vector<const subtree*>& result, Pred& p) const
00329     {
00330         if (p(*content))
00331         {
00332             result.push_back(this);
00333         }
00334 
00335         for (int i = 0; i < arity(); ++i)
00336         {
00337             args[i].find_nodes(result, p);
00338         }
00339     }
00340 
00341         /* Iterators */
00342 
00343     iterator begin(void)              { return args; }
00344     const_iterator begin(void) const  { return args; }
00345 
00346     iterator end(void)                { return args + arity(); }
00347     const_iterator end(void) const    { return args + arity(); }
00348 
00349         subtree& operator[](int i)                { return *(begin() + i); }
00350         const subtree& operator[](int i) const { return *(begin() + i); }
00351 
00352         /* Some statistics */
00353 
00354     size_t size(void) const { return _size; }
00355 
00356     size_t cumulative_size(void) const { return _cumulative_size; }
00357     size_t depth(void) const           { return _depth; }
00358 
00359     const subtree& select_cumulative(size_t which) const
00360     { return imp_select_cumulative(which); }
00361 
00362     subtree& select_cumulative(size_t which)
00363     { return const_cast<subtree&>(imp_select_cumulative(which)); }
00364 
00365     subtree& get_node(size_t which)
00366     { return const_cast<subtree&>(imp_get_node(which));}
00367     const subtree& get_node(size_t which) const
00368     { return imp_get_node(which); }
00369 
00370     subtree*       get_parent(void)        { return parent; }
00371     const subtree* get_parent(void) const  { return parent; }
00372 
00373         void clear(void)
00374         { tree_allocator.deallocate(args, arity()); args = 0; *content = T(); parent = 0; _cumulative_size = 0; _depth = 0; _size = 0; }
00375 
00376         void swap(subtree& y)
00377         {
00378         do_the_swap(content, y.content);
00379         do_the_swap(args, y.args);
00380 
00381         adopt();
00382         y.adopt();
00383 
00384         do_the_swap(parent, y.parent);
00385 
00386         do_the_swap(_cumulative_size, y._cumulative_size);
00387         do_the_swap(_depth, y._depth);
00388         do_the_swap(_size, y._size);
00389                 updateAfterInsert();
00390         }
00391 
00392 protected :
00393 
00394         virtual void updateAfterInsert(void)
00395     {
00396         _depth = 0;
00397         _size = 1;
00398         _cumulative_size = 0;
00399 
00400         for (iterator it = begin(); it != end(); ++it)
00401         {
00402             _size += it->size();
00403             _cumulative_size += it->_cumulative_size;
00404             _depth = it->_depth > _depth? it->_depth: _depth;
00405         }
00406         _cumulative_size += _size;
00407         _depth++;
00408 
00409         if (parent)
00410             parent->updateAfterInsert();
00411     }
00412 
00413 private :
00414 
00415     const subtree& imp_select_cumulative(size_t which) const
00416     {
00417         if (which >= (_cumulative_size - size()))
00418             return *this;
00419         // else
00420 
00421         for (int i = arity() - 1; i >= 0; --i)
00422                 {
00423             if (which < args[i]._cumulative_size)
00424                 return args[i].imp_select_cumulative(which);
00425             which -= args[i]._cumulative_size;
00426         }
00427 
00428         return *this; // error!
00429     }
00430 
00431     const subtree& imp_get_node(size_t which) const
00432     {
00433         if (which == size() - 1)
00434             return *this;
00435 
00436         for (int i = arity() - 1; i >= 0; --i)
00437                 {
00438             unsigned c_size = args[i].size();
00439             if (which < c_size)
00440                 return args[i].imp_get_node(which);
00441             which -= c_size;
00442         }
00443 
00444         return *this; // error!
00445     }
00446 
00447     const subtree* get_root(void) const
00448     {
00449         if (parent == 0)
00450             return this;
00451         // else
00452 
00453         return parent->get_root();
00454     }
00455     subtree& copy(const subtree& s)
00456     {
00457                 int old_arity = arity();
00458 
00459                 int new_arity = s.arity();
00460 
00461                 if (new_arity != old_arity)
00462                 {
00463                         tree_allocator.deallocate(args, old_arity);
00464 
00465             args = tree_allocator.allocate(new_arity);
00466                 }
00467 
00468                 switch(new_arity)
00469                 {
00470                 case 3 : args[2].copy(s.args[2]); args[2].parent = this; // no break!
00471                 case 2 : args[1].copy(s.args[1]); args[1].parent = this;
00472                 case 1 : args[0].copy(s.args[0]); args[0].parent = this;
00473                 case 0 : break;
00474                 default :
00475                         {
00476                                 for (int i = 0; i < new_arity; ++i)
00477                                 {
00478                                         args[i].copy(s.args[i]);
00479                     args[i].parent = this;
00480                                 }
00481                         }
00482                 }
00483 
00484                 *content = *s.content;
00485         _size = s._size;
00486         _depth = s._depth;
00487         _cumulative_size = s._cumulative_size;
00488 
00489         return *this;
00490     }
00491 
00492     subtree& copy(const T& t)
00493     {
00494         int oldArity = arity();
00495 
00496                 if (content != &t)
00497             *content = t;
00498                 else
00499                         oldArity = -1;
00500 
00501                 int ar = arity();
00502 
00503                 if (ar != oldArity)
00504                 {
00505             if (oldArity != -1)
00506                             tree_allocator.deallocate(args, oldArity);
00507 
00508             args = tree_allocator.allocate(ar);
00509 
00510             //if (ar > 0)
00511                         //      args = new subtree [ar];
00512                         //else
00513                         //      args = 0;
00514                 }
00515 
00516         adopt();
00517         updateAfterInsert();
00518                 return *this;
00519     }
00520 
00521         void disown(void)
00522         {
00523                 switch(arity())
00524                 {
00525                 case 3 : args[2].parent = 0; // no break!
00526                 case 2 : args[1].parent = 0;
00527                 case 1 : args[0].parent = 0; break;
00528                 case 0 : break;
00529                 default :
00530                         {
00531                                 for (iterator it = begin(); it != end(); ++it)
00532                                 {
00533                                         it->parent = 0;
00534                                 }
00535                         }
00536                 }
00537 
00538         }
00539 
00540     void adopt(void)
00541     {
00542                 switch(arity())
00543                 {
00544                 case 3 : args[2].parent = this; // no break!
00545                 case 2 : args[1].parent = this;
00546                 case 1 : args[0].parent = this; break;
00547                 case 0 : break;
00548                 default :
00549                         {
00550                                 for (iterator it = begin(); it != end(); ++it)
00551                                 {
00552                                         it->parent = this;
00553                                 }
00554                         }
00555                 }
00556     }
00557 
00558     template <class It>
00559     void init(It b, It& last)
00560     {
00561         *this = *last;
00562 
00563 #ifndef NDEBUG
00564         if (last == b && arity() > 0)
00565         {
00566             throw "subtree::init()";
00567         }
00568 #endif
00569 
00570         for (int i = 0; i < arity(); ++i)
00571         {
00572             args[i].parent = 0;
00573             args[i].init(b, --last);
00574             args[i].parent = this;
00575         }
00576 
00577         updateAfterInsert();
00578     }
00579 
00580     T* content;
00581     subtree*                    args;
00582     subtree*                    parent;
00583 
00584         size_t _cumulative_size;
00585     size_t _depth;
00586     size_t _size;
00587 };
00588 
00589 // Continuing with parse_tree
00590 
00591     typedef T value_type;
00592 
00593         /* Constructors and Assignments */
00594 
00595     parse_tree(void) : _root(), pushed() {}
00596     parse_tree(const parse_tree& org) : _root(org._root), pushed(org.pushed) { }
00597     parse_tree(const subtree& sub) : _root(sub), pushed() { }
00598 
00599     template <class It>
00600         parse_tree(It b, It e) : _root(b, e), pushed() {}
00601 
00602     virtual ~parse_tree(void) {}
00603 
00604     parse_tree& operator=(const parse_tree& org) { return copy(org); }
00605         parse_tree& operator=(const subtree& sub)
00606                 { return copy(sub); }
00607 
00608 
00609         /* Equality and inequality */
00610 
00611         bool operator==(const parse_tree& other) const
00612         { return _root == other._root; }
00613 
00614         bool operator !=(const parse_tree& other) const
00615         { return !operator==(other); }
00616 
00617         /* Simple tree statistics */
00618 
00619     size_t size(void) const  { return _root.size(); }
00620         size_t depth(void) const { return _root.depth(); }
00621     void clear(void)        { _root.clear(); pushed.resize(0); }
00622 
00623         /* Evaluation (application), with an increasing number of user defined arguments */
00624 
00625         template <class RetVal>
00626         void apply(RetVal& v) const
00627                 { _root.apply(v); }
00628 
00629         template <class RetVal, class It>
00630                 void apply(RetVal& v, It varValues) const
00631                 { _root.apply(v, varValues); }
00632 
00633     template <class RetVal, class It>
00634         void apply_mem_func(RetVal& v, It misc, void (T::* f)(RetVal&, typename subtree::iterator, It))
00635     {
00636         _root.apply_mem_func(v, misc, f);
00637     }
00638 
00639         //template <class RetVal, class It, class It2>
00640         //      void apply(RetVal& v, It varValues, It2 moreValues) const
00641         //      { _root.apply(v, varValues, moreValues); }
00642 
00643         //template <class RetVal, class It, class It2, class It3>
00644         //      void apply(RetVal& v, It varValues, It2 moreValues, It3 evenMoreValues) const
00645         //      { _root.apply(v, varValues, moreValues, evenMoreValues); }
00646 
00647     template <class Pred>
00648     void find_nodes(std::vector<subtree*>& result, Pred& p)
00649     {
00650         _root.find_nodes(result, p);
00651     }
00652 
00653     template <class Pred>
00654     void find_nodes(std::vector<const subtree*>& result, Pred& p) const
00655     {
00656         _root.find_nodes(p);
00657     }
00658 
00659         /* Customized Swap */
00660         void swap(parse_tree<T>& other)
00661         {
00662                 do_the_swap(pushed, other.pushed);
00663                 _root.swap(other._root);
00664         }
00665 
00666         /* Definitions of the iterators */
00667 
00668     class base_iterator
00669     {
00670     public :
00671 
00672         base_iterator() {}
00673         base_iterator(subtree* n)  { node = n; }
00674 
00675         base_iterator& operator=(const base_iterator& org)
00676         { node = org.node; return *this; }
00677 
00678         bool operator==(const base_iterator& org) const
00679         { return node == org.node; }
00680         bool operator!=(const base_iterator& org) const
00681         { return !operator==(org); }
00682 
00683                 base_iterator operator+(size_t n) const
00684                 {
00685                         base_iterator tmp = *this;
00686 
00687                         for(;n != 0; --n)
00688                         {
00689                                 ++tmp;
00690                         }
00691 
00692                         return tmp;
00693                 }
00694 
00695                 base_iterator& operator++(void)
00696         {
00697             subtree* parent = node->get_parent();
00698 
00699             if (parent == 0)
00700             {
00701                 node = 0;
00702                 return *this;
00703             }
00704             // else
00705             typename subtree::iterator it;
00706             for (it = parent->begin(); it != parent->end(); ++it)
00707             {
00708                 if (node == &(*it))
00709                     break;
00710             }
00711 
00712             if (it == parent->begin())
00713                 node = parent;
00714             else
00715             {
00716                 node = &(--it)->get_node(0);
00717             }
00718 
00719             return *this;
00720         }
00721 
00722         base_iterator operator++(int)
00723         {
00724             base_iterator tmp = *this;
00725             operator++();
00726             return tmp;
00727         }
00728 
00729     protected :
00730         subtree* node;
00731     };
00732 
00733     class iterator : public base_iterator
00734     {
00735     public:
00736 
00737         using base_iterator::node;
00738 
00739         typedef std::forward_iterator_tag iterator_category;
00740         typedef subtree value_type;
00741         typedef size_t distance_type;
00742         typedef size_t difference_type;
00743         typedef subtree* pointer;
00744         typedef subtree& reference;
00745 
00746         iterator() : base_iterator() {}
00747         iterator(subtree* n): base_iterator(n)  {}
00748         iterator& operator=(const iterator& org)
00749         { base_iterator::operator=(org); return *this; }
00750 
00751         subtree& operator*(void)  { return *node; }
00752         subtree* operator->(void) { return node; }
00753     };
00754 
00755 
00756 
00757     class embedded_iterator : public base_iterator
00758     {
00759     public:
00760 
00761         using base_iterator::node;
00762 
00763         typedef std::forward_iterator_tag iterator_category;
00764         typedef T value_type;
00765         typedef size_t distance_type;
00766         typedef size_t difference_type;
00767         typedef T* pointer;
00768         typedef T& reference;
00769 
00770         embedded_iterator() : base_iterator() {}
00771         embedded_iterator(subtree* n): base_iterator(n)  {}
00772         embedded_iterator& operator=(const embedded_iterator& org)
00773         { base_iterator::operator=(org); return *this; }
00774 
00775         T&  operator*(void)  { return **node; }
00776         T* operator->(void) { return &**node; }
00777     };
00778 
00779     class base_const_iterator
00780     {
00781     public:
00782 
00783         base_const_iterator() {}
00784         base_const_iterator(const subtree* n)  { node = n; }
00785 
00786         base_const_iterator& operator=(const base_const_iterator& org)
00787         { node = org.node; return *this; }
00788 
00789         bool operator==(const base_const_iterator& org) const
00790         { return node == org.node; }
00791         bool operator!=(const base_const_iterator& org) const
00792         { return !operator==(org); }
00793 
00794         base_const_iterator& operator++(void)
00795         {
00796             const subtree* parent = node->get_parent();
00797 
00798             if (parent == 0)
00799             {
00800                 node = 0;
00801                 return *this;
00802             }
00803             // else
00804             typename subtree::const_iterator it;
00805 
00806             for (it = parent->begin(); it != parent->end(); ++it)
00807             {
00808                 if (node == &(*it))
00809                     break;
00810             }
00811 
00812             if (it == parent->begin())
00813                 node = parent;
00814             else
00815                 node = &(--it)->get_node(0);
00816             return *this;
00817         }
00818 
00819         base_const_iterator operator++(int)
00820         {
00821             base_const_iterator tmp = *this;
00822             operator++();
00823             return tmp;
00824         }
00825 
00826     protected :
00827 
00828         const subtree* node;
00829     };
00830 
00831     class const_iterator : public base_const_iterator
00832     {
00833     public:
00834 
00835         using base_const_iterator::node;
00836 
00837         typedef std::forward_iterator_tag iterator_category;
00838         typedef const subtree value_type;
00839         typedef size_t distance_type;
00840         typedef size_t difference_type;
00841         typedef const subtree* pointer;
00842         typedef const subtree& reference;
00843 
00844         const_iterator() : base_const_iterator() {}
00845         const_iterator(const subtree* n): base_const_iterator(n)  {}
00846         const_iterator& operator=(const const_iterator& org)
00847         { base_const_iterator::operator=(org); return *this; }
00848 
00849         const subtree& operator*(void)  { return *node; }
00850         const subtree* operator->(void) { return node; }
00851     };
00852 
00853     class embedded_const_iterator : public base_const_iterator
00854     {
00855     public:
00856 
00857         using base_const_iterator::node;
00858 
00859                 typedef std::forward_iterator_tag iterator_category;
00860                 typedef const T value_type;
00861                 typedef size_t distance_type;
00862                 typedef size_t difference_type;
00863                 typedef const T* pointer;
00864                 typedef const T& reference;
00865 
00866         embedded_const_iterator() : base_const_iterator() {}
00867         embedded_const_iterator(const subtree* n): base_const_iterator(n)  {}
00868         embedded_const_iterator& operator=(const embedded_const_iterator& org)
00869         { base_const_iterator::operator=(org); return *this; }
00870 
00871                 embedded_const_iterator operator+(size_t n) const
00872                 {
00873                         embedded_const_iterator tmp = *this;
00874 
00875                         for(;n != 0; --n)
00876                         {
00877                                 ++tmp;
00878                         }
00879 
00880                         return tmp;
00881                 }
00882 
00883         const T&  operator*(void)  const { return **node; }
00884         const T*  operator->(void) const { return node->operator->(); }
00885     };
00886 
00887         /* Iterator access */
00888 
00889     iterator begin(void)            { return iterator(&operator[](0)); }
00890     const_iterator begin(void) const { return const_iterator(&operator[](0)); }
00891     iterator end(void)               { return iterator(0); }
00892     const_iterator end(void) const   { return const_iterator(0);}
00893 
00894     embedded_iterator       ebegin(void)       { return embedded_iterator(&operator[](0)); }
00895     embedded_const_iterator ebegin(void) const { return embedded_const_iterator(&operator[](0)); }
00896     embedded_iterator       eend(void)         { return embedded_iterator(0); }
00897     embedded_const_iterator eend(void) const   { return embedded_const_iterator(0);}
00898 
00899     bool empty(void) const { return size() == 0; }
00900     bool valid(void) const { return pushed.empty(); }
00901 
00902         /* push_back */
00903 
00904         void push_back(const parse_tree<T>& tree)
00905         {
00906                 if (!empty())
00907                         pushed.push_back(_root);
00908 
00909                 _root = tree.back();
00910         }
00911 
00912     void push_back(const T& t)
00913     {
00914         if (!empty())
00915             pushed.push_back(_root);
00916 
00917                 _root = t;
00918 
00919         for (typename subtree::iterator it = _root.begin(); it != _root.end(); it++)
00920         {
00921                         *it = pushed.back();
00922             pushed.pop_back();
00923         }
00924 
00925     }
00926 
00927         /* Access to subtrees */
00928 
00929     subtree& back(void)              { return _root; }
00930     const subtree& back(void) const  { return _root; }
00931     subtree& root(void)              { return _root; }
00932     const subtree& root(void) const  { return _root; }
00933 
00934     subtree& front(void)              { return _root[0]; }
00935     const subtree& front(void) const  { return _root[0]; }
00936 
00937     subtree& operator[](size_t i)
00938     { return const_cast<subtree&>(_root.get_node(i)); }
00939     const subtree& operator[](size_t i) const
00940     { return _root.get_node(i); }
00941 
00942     subtree& get_cumulative(size_t i)
00943     { return const_cast<subtree&>(_root.get_cumulative(i)); }
00944     const subtree& get_cumulative(size_t i) const
00945     { return get_cumulative(i); }
00946 
00947     private :
00948 
00949     parse_tree& copy(const parse_tree& org)
00950     {
00951         _root = org._root;
00952         pushed = org.pushed;
00953 
00954         return *this;
00955     }
00956 
00957         parse_tree& copy(const subtree& sub)
00958     { _root = sub; pushed.resize(0); return *this; }
00959 
00960     subtree _root;
00961     std::vector<subtree > pushed;
00962 }; // end class parse_tree
00963 
00964 
00965 } // end namespace gp_parse_tree
00966 
00967 namespace std
00968 { // for use with stlport on MSVC
00969 
00970 template <class T> inline
00971 std::forward_iterator_tag iterator_category(typename gp_parse_tree::parse_tree<T>::embedded_iterator)
00972 {
00973         return std::forward_iterator_tag();
00974 }
00975 
00976 template <class T> inline
00977 ptrdiff_t*  distance_type(typename gp_parse_tree::parse_tree<T>::embedded_iterator)
00978 {
00979         return 0;
00980 }
00981 
00982 template <class T> inline
00983 std::forward_iterator_tag iterator_category(typename gp_parse_tree::parse_tree<T>::iterator)
00984 {
00985         return std::forward_iterator_tag();
00986 }
00987 
00988 template <class T> inline
00989 ptrdiff_t*  distance_type(typename gp_parse_tree::parse_tree<T>::iterator)
00990 {
00991         return 0;
00992 }
00993 
00994 /* Put customized swaps also in std...
00995 
00996 template<class T> inline
00997 void swap(gp_parse_tree::parse_tree<T>& a, gp_parse_tree::parse_tree<T>& b)
00998 {
00999     a.swap(b);
01000 }
01001 
01002 template<class T> inline
01003 void iter_swap(std::vector<gp_parse_tree::parse_tree<T> >::iterator a, std::vector<gp_parse_tree::parse_tree<T> > b)
01004 {
01005     a->swap(*b);
01006 }*/
01007 
01008 
01009 } // namespace std
01010 
01011 
01012 #endif
 All Classes Namespaces Files Functions Variables Typedefs Friends