Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-06 09:24:22

0001 // -*- C++ -*-
0002 //
0003 // binary_tree.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
0004 //
0005 // Copyright (C) 2008-2019 Simon Platzer -- simon.plaetzer@desy.de, The Herwig Collaboration
0006 //
0007 // ExSample is licenced under version 3 of the GPL, see COPYING for details.
0008 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
0009 //
0010 //
0011 #ifndef EXSAMPLE_binary_tree_h_included
0012 #define EXSAMPLE_binary_tree_h_included
0013 
0014 #include "utility.h"
0015 
0016 namespace exsample {
0017 
0018   /// \brief binary_tree represents a binary tree with the ability to
0019   /// `cascade' visitor objects down the tree
0020   template<class Value>
0021   class binary_tree {
0022 
0023   public:
0024 
0025     ///@name type definitions
0026     //@{
0027 
0028     /// define the object type
0029     typedef Value value_type;
0030 
0031     //@}
0032 
0033   public:
0034 
0035     ///@name constructors
0036     //@{
0037 
0038     /// default constructor
0039     binary_tree()
0040       : neighbours_(),
0041     parent_(), value_(),
0042     children_()
0043     { }
0044 
0045     /// construct giving key/cell and parent
0046     binary_tree(const value_type& thevalue,
0047         binary_tree * theparent = 0)
0048       : neighbours_(), parent_(theparent),
0049     value_(new value_type(thevalue)),
0050     children_()
0051     { }
0052 
0053     /// binary_tree has a strict ownership; on copying
0054     /// binary trees ownership is transferred
0055     binary_tree(const binary_tree& x)
0056       : neighbours_(x.neighbours_),
0057     parent_(x.parent_), value_(),
0058     children_() {
0059       assert(x.root());
0060       binary_tree& nc_x = const_cast<binary_tree&>(x);
0061       value_.swap(nc_x.value_);
0062       children_.first.swap(nc_x.children_.first);
0063       children_.second.swap(nc_x.children_.second);
0064       nc_x.parent_ = 0;
0065       nc_x.neighbours_.first = 0;
0066       nc_x.neighbours_.second = 0;
0067     }
0068 
0069     /// binary_tree has a strict ownership; on copying
0070     /// binary trees ownership is transferred
0071     binary_tree& operator=(const binary_tree& x) {
0072       if (this == &x)
0073     return *this;
0074       assert(x.root());
0075       binary_tree& nc_x = const_cast<binary_tree&>(x);
0076       value_.swap(nc_x.value_);
0077       children_.first.swap(nc_x.children_.first);
0078       children_.second.swap(nc_x.children_.second);
0079       neighbours_ = x.neighbours_;
0080       parent_ = x.parent_;
0081       nc_x.parent_ = 0;
0082       nc_x.neighbours_.first = 0;
0083       nc_x.neighbours_.second = 0;
0084       return *this;
0085     }
0086 
0087     //@}
0088 
0089     ///@name standard-conforming leaf iterators
0090     //@{
0091 
0092   public:
0093 
0094     class const_iterator;
0095 
0096     /// iterator
0097     class iterator {
0098 
0099     public:
0100 
0101       ///@name type definitions for iterator traits
0102       //@{
0103 
0104       /// define the iterator category
0105       typedef std::bidirectional_iterator_tag iterator_category;
0106 
0107       /// define the difference_type
0108       typedef int difference_type;
0109 
0110       /// define the value type
0111       typedef Value value_type;
0112 
0113       /// define the reference type
0114       typedef value_type& reference;
0115 
0116       /// define the pointer type
0117       typedef value_type * pointer;
0118 
0119       //@}
0120 
0121     public:
0122 
0123       ///@name constructors
0124       //@{
0125 
0126       /// default constructor
0127       iterator() : pointee(0), post_end(0), pre_begin(0) { }
0128 
0129       /// constructor taking pointee
0130       iterator(binary_tree * p, std::size_t end = 0)
0131     : pointee(p), post_end(end), pre_begin(0) { }
0132 
0133       //@
0134 
0135     public:
0136 
0137       ///@name comparisons
0138       //@{
0139 
0140       /// comparison
0141       bool operator==(const iterator& x) const {
0142     return ((pointee == x.pointee) &&
0143         (post_end == x.post_end) &&
0144         (pre_begin == x.pre_begin));
0145       }
0146 
0147       /// comparison
0148       bool operator!=(const iterator& x) const { return !(*this == x); }
0149 
0150       //@}
0151 
0152     public:
0153 
0154       ///@name derefrence and indirection
0155       //@{
0156 
0157       /// dereference
0158       reference operator*() { return pointee->value(); }
0159 
0160       /// indirection
0161       pointer operator->() { return &**this; }
0162 
0163       /// return reference to the node
0164       binary_tree& node() { return *pointee; }
0165 
0166       //@}
0167 
0168       /// return raw pointer to the element pointed to
0169       binary_tree * get() const { return pointee; }
0170 
0171       ///@name biderectional iterator increment/decrements
0172       //@{
0173 
0174       /// pre-increment
0175       iterator& operator++() {
0176     if (post_end) { ++post_end; return *this; }
0177     if (pre_begin) { --pre_begin; return *this; }
0178     if(!(pointee->right_neighbour())) { post_end = 1; return *this; }
0179     pointee = pointee->right_neighbour();
0180     return *this;
0181       }
0182 
0183       /// pre-decrement
0184       iterator& operator--() {
0185     if (post_end) { --post_end; return *this; }
0186     if (pre_begin) { ++pre_begin; return *this; }
0187     if(!(pointee->left_neighbour())) { pre_begin = 1; return *this; }
0188     pointee = pointee->left_neighbour();
0189     return *this;
0190       }
0191 
0192       /// post-increment
0193       iterator operator++(int) {
0194     iterator tmp = *this;
0195     ++(*this);
0196     return tmp;
0197       }
0198       
0199       /// post-decrement
0200       iterator operator--(int) {
0201     iterator tmp = *this;
0202     --(*this);
0203     return tmp;
0204       }
0205       
0206       //@}
0207 
0208     private:
0209 
0210       /// friend for conversion
0211       friend class const_iterator;
0212 
0213       /// the node pointed to
0214       binary_tree * pointee;
0215 
0216       /// the distance from --end() (if above --end())
0217       std::size_t post_end;
0218 
0219       /// the distance from begin() (if below begin())
0220       std::size_t pre_begin;
0221 
0222     };
0223 
0224     /// return begin iterator
0225     iterator begin() { return iterator(left_most()); }
0226 
0227     /// return end iterator
0228     iterator end() { return iterator(right_most(),1); }
0229 
0230     /// return global begin iterator
0231     iterator global_begin() { 
0232       if (!root())
0233     return parent().global_begin();
0234       return iterator(left_most());
0235     }
0236 
0237     /// return global end iterator
0238     iterator global_end() {
0239       if (!root())
0240     return parent().global_end();
0241       return iterator(right_most(),1);
0242     }
0243 
0244     /// const_iterator
0245     class const_iterator {
0246 
0247     public:
0248 
0249       ///@name type definitions for iterator traits
0250       //@{
0251 
0252       /// define the iterator category
0253       typedef std::bidirectional_iterator_tag iterator_category;
0254 
0255       /// define the difference type
0256       typedef int difference_type;
0257 
0258       /// define the value type
0259       typedef const Value value_type;
0260 
0261       /// define the reference type
0262       typedef const value_type& reference;
0263 
0264       /// define the pointer type
0265       typedef const value_type * pointer;
0266 
0267       //@}
0268 
0269     public:
0270 
0271       ///@name constructors
0272       //@{
0273 
0274       /// default constructor
0275       const_iterator() : pointee(0), post_end(0), pre_begin(0) { }
0276 
0277       /// constructor taking pointee
0278       const_iterator(const binary_tree * p, std::size_t end = 0)
0279     : pointee(p), post_end(end), pre_begin(0) { }
0280 
0281       /// conversion from iterator
0282       const_iterator(const iterator& x)
0283     : pointee(x.pointee), post_end(x.post_end), pre_begin(x.pre_begin) { }
0284 
0285       //@}
0286 
0287     public:
0288 
0289       ///@name comparisons
0290       //@{
0291 
0292       /// comparison
0293       bool operator==(const const_iterator& x) const { 
0294     return ((pointee == x.pointee) &&
0295         (post_end == x.post_end) &&
0296         (pre_begin == x.pre_begin));
0297       }
0298 
0299       /// comparison
0300       bool operator!=(const const_iterator& x) const { return !(*this == x); }
0301 
0302       //@}
0303 
0304     public:
0305 
0306       ///@name dereference and indirection
0307       //@{
0308 
0309       /// dereference
0310       reference operator*() const { return pointee->value(); }
0311 
0312       /// indirection
0313       pointer operator->() const { return &**this; }
0314 
0315       /// return reference to the node
0316       const binary_tree& node() const { return *pointee; }
0317 
0318       //@}
0319 
0320       ///@name biderectional iterator increment/decrements
0321       //@{
0322 
0323       /// pre-increment
0324       const_iterator& operator++() {
0325     if (post_end) { ++post_end; return *this; }
0326     if (pre_begin) { --pre_begin; return *this; }
0327     if(!(pointee->right_neighbour())) { post_end = 1; return *this; }
0328     pointee = pointee->right_neighbour();
0329     return *this;
0330       }
0331 
0332       /// pre-decrement
0333       const_iterator& operator--() {
0334     if (post_end) { --post_end; return *this; }
0335     if (pre_begin) { ++pre_begin; return *this; }
0336     if(!(pointee->left_neighbour())) { pre_begin = 1; return *this; }
0337     pointee = pointee->left_neighbour();
0338     return *this;
0339       }
0340 
0341       /// post-increment
0342       const_iterator operator++(int) {
0343     const_iterator tmp = *this;
0344     ++(*this);
0345     return tmp;
0346       }
0347       
0348       /// post-decrement
0349       const_iterator operator--(int) {
0350     const_iterator tmp = *this;
0351     --(*this);
0352     return tmp;
0353       }
0354 
0355       //@}
0356 
0357     private:
0358 
0359       /// the node pointed to
0360       const binary_tree * pointee;
0361 
0362       /// the distance from --end() (if above --end())
0363       std::size_t post_end;
0364 
0365       /// the distance from begin() (if below begin())
0366       std::size_t pre_begin;
0367 
0368     };
0369 
0370     /// return begin const_iterator
0371     const_iterator begin() const { return const_iterator(left_most()); }
0372 
0373     /// return end const_iterator
0374     const_iterator end() const { return const_iterator(right_most(),1); }
0375 
0376     /// return global begin iterator
0377     const_iterator global_begin() const { 
0378       if (!root())
0379     return parent().global_begin();
0380       return iterator(left_most());
0381     }
0382 
0383     /// return global end iterator
0384     const_iterator global_end() const {
0385       if (!root())
0386     return parent().global_end();
0387       return iterator(right_most(),1);
0388     }
0389 
0390   private:
0391 
0392     /// set the left neighbour
0393     void left_neighbour(binary_tree * n) { neighbours_.first = n; }
0394 
0395     /// set the right neighbour
0396     void right_neighbour(binary_tree * n) { neighbours_.second = n; }
0397 
0398     /// get the left neighbour
0399     binary_tree * left_neighbour() const { return neighbours_.first; }
0400 
0401     /// get the right neighbour
0402     binary_tree * right_neighbour() const { return neighbours_.second; }
0403 
0404     /// return the left-most leaf
0405     binary_tree * left_most() {
0406       if(leaf()) return this;
0407       return left_child().left_most();
0408     }
0409 
0410     /// return the right-most leaf
0411     binary_tree * right_most() {
0412       if(leaf()) return this;
0413       return right_child().right_most();
0414     }
0415 
0416     /// return the left-most leaf
0417     const binary_tree * left_most() const {
0418       if(leaf()) return this;
0419       return left_child().left_most();
0420     }
0421 
0422     /// return the right-most leaf
0423     const binary_tree * right_most() const {
0424       if(leaf()) return this;
0425       return right_child().right_most();
0426     }
0427 
0428     /// the left and right neighbours of this node
0429     std::pair<binary_tree*,binary_tree*> neighbours_;
0430 
0431     //@}
0432 
0433   public:
0434 
0435     /// return true, if this node is empty
0436     bool empty() const { return root() && leaf() && !value_; }
0437 
0438     /// clear this node
0439     void clear() {
0440       neighbours_ = std::make_pair<binary_tree*,binary_tree*>(0,0);
0441       parent_ = 0;
0442       value_.reset(0);
0443       if (!leaf()) {
0444     left_child().clear();
0445     right_child().clear();
0446       }
0447       children_.first.reset(0);
0448       children_.second.reset(0);
0449     }
0450 
0451   public:
0452 
0453     /// split this node
0454     std::pair<iterator,iterator> split(std::pair<value_type,value_type> children) {
0455 
0456       assert(leaf());
0457 
0458       children_.first.reset(new binary_tree(children.first,this));
0459       children_.second.reset(new binary_tree(children.second,this));
0460 
0461       children_.first->left_neighbour(neighbours_.first);
0462       children_.first->right_neighbour(children_.second.get());
0463       children_.second->left_neighbour(children_.first.get());
0464       children_.second->right_neighbour(neighbours_.second);
0465 
0466       // adjust original neighbours
0467       
0468       if(neighbours_.first) {
0469     neighbours_.first->right_neighbour(children_.first.get());
0470       }
0471 
0472       if (neighbours_.second) {
0473     neighbours_.second->left_neighbour(children_.second.get());
0474       }
0475 
0476       neighbours_.first = 0; neighbours_.second = 0;
0477 
0478       return std::make_pair(iterator(children_.first.get()),iterator(children_.second.get()));
0479 
0480     }
0481 
0482   public:
0483 
0484     /// select using a selector
0485     template<class Selector>
0486     iterator select(const Selector& selector) {
0487 
0488       if(leaf()) {
0489     bool use = selector.use(value());
0490     if (use) return iterator(this);
0491     return global_end();
0492       }
0493 
0494       std::pair<bool,bool> which(selector.use(value(),left_child().value(),right_child().value()));
0495 
0496       assert(!which.first || !which.second);
0497 
0498       if (!which.first && !which.second) {
0499     return global_end();
0500       }
0501 
0502       if (which.first) {
0503     return left_child().select(selector);
0504       }
0505       else {
0506     return right_child().select(selector);
0507       }
0508 
0509       return global_end();
0510 
0511     }
0512 
0513     /// generate a hash value for the sub-tree
0514     /// selected by the given selector object
0515     template<class Selector, unsigned long bits>
0516     void subtree_hash(const Selector& selector, bit_container<bits>& bhash) {
0517       bhash = bit_container<bits>();
0518       unsigned long pos = 0;
0519       do_subtree_hash<Selector,bits>(selector,bhash,pos);
0520     }
0521 
0522     /// accumulate values using a binary function
0523     /// and accessor object
0524     template<class Accessor, class BinaryOp>
0525     typename BinaryOp::result_type accumulate(const Accessor& acc,
0526                           BinaryOp binary_op) const {
0527 
0528       if (!leaf()) {
0529     return
0530       binary_op(left_child().accumulate(acc,binary_op),
0531             right_child().accumulate(acc,binary_op));
0532       }
0533 
0534       return acc.get(value(),true);
0535 
0536     }
0537 
0538     /// accumulate values only from branches
0539     /// matching a Selector
0540     template<class Selector, class Accessor, class BinaryOp>
0541     typename BinaryOp::result_type accumulate(const Selector& selector,
0542                           const Accessor& acc,
0543                           BinaryOp binary_op) const {
0544 
0545       if (!leaf()) {
0546     std::pair<bool,bool> which(selector.use(value(),left_child().value(),right_child().value()));
0547     assert(which.first || which.second);
0548     if (which.first && which.second) {
0549       return
0550         binary_op(left_child().accumulate(selector,acc,binary_op),
0551               right_child().accumulate(selector,acc,binary_op));
0552     } else if (which.first) {
0553       return left_child().accumulate(selector,acc,binary_op);
0554     } else if (which.second) {
0555       return right_child().accumulate(selector,acc,binary_op);
0556     }
0557       }
0558 
0559       return acc.get(value(),true);
0560 
0561     }
0562 
0563     /// accumulate values using a binary function
0564     /// and accessor object, storing intermediate
0565     /// values in nodes
0566     template<class Accessor, class BinaryOp>
0567     typename BinaryOp::result_type tree_accumulate(const Accessor& acc,
0568                            BinaryOp binary_op) {
0569 
0570       if (!leaf()) {
0571     acc.set(value()) =
0572       binary_op(left_child().tree_accumulate(acc,binary_op),
0573             right_child().tree_accumulate(acc,binary_op));
0574     return acc.get(value(),false);
0575       }
0576 
0577       acc.set(value()) = acc.get(value(),true);
0578       return acc.get(value(),true);
0579 
0580     }
0581 
0582     /// accumulate values only from branches
0583     /// matching a Selector
0584     template<class Selector, class Accessor, class BinaryOp>
0585     typename BinaryOp::result_type tree_accumulate(const Selector& selector,
0586                            const Accessor& acc,
0587                            BinaryOp binary_op) {
0588 
0589       if (!leaf()) {
0590     std::pair<bool,bool> which(selector.use(value(),left_child().value(),right_child().value()));
0591     assert(which.first || which.second);
0592     if (which.first && which.second) {
0593       acc.set(value()) =
0594         binary_op(left_child().tree_accumulate(selector,acc,binary_op),
0595               right_child().tree_accumulate(selector,acc,binary_op));
0596     } else if (which.first) {
0597       acc.set(value()) = left_child().tree_accumulate(selector,acc,binary_op);
0598     } else if (which.second) {
0599       acc.set(value()) = right_child().tree_accumulate(selector,acc,binary_op);
0600     }
0601     return acc.get(value(),false);
0602       }
0603 
0604       acc.set(value()) = acc.get(value(),true);
0605       return acc.get(value(),true);
0606 
0607     }
0608 
0609     /// forward propagate a visitor to all children nodes
0610     template<class Visitor>
0611     void cascade(Visitor visitor) const {
0612       if (leaf()) {
0613     visitor.visit(value()); 
0614     return;
0615       } else visitor.visit(value(),left_child().value(),right_child().value());
0616       left_child().cascade(visitor);
0617       right_child().cascade(visitor);
0618     }
0619 
0620     /// succesively split using a generator
0621     template<class Generator>
0622     void generate(Generator generator) {
0623       if (root())
0624     value_.reset(new value_type(generator.root()));
0625       if (generator.split()) {
0626     std::pair<iterator,iterator> ch = split(generator.generate(value()));
0627     ch.first.node().generate(generator);
0628     ch.second.node().generate(generator);
0629       }
0630     }
0631 
0632   public:
0633 
0634     ///@name Public member access
0635     //@{
0636 
0637     /// return the value held by this node
0638     value_type& value() { return *value_; }
0639 
0640     /// return the value held by this node
0641     const value_type& value() const { return *value_; }
0642 
0643     /// return true, if this is the root node
0644     bool root() const { return !parent_; }
0645 
0646     /// return true, if this node has got children
0647     bool leaf() const { return !(children_.first.get() && children_.second.get()); }
0648 
0649     //@}
0650 
0651   public:
0652 
0653     ///@name put and get from streams
0654     //@{
0655 
0656     /// forward visitor writing out the tree to given ostream
0657     template<class OStream>
0658     struct ostream_visitor {
0659 
0660       /// construct from ostream reference
0661       explicit ostream_visitor(OStream& os) : os_(&os), first_time_(true) {}
0662 
0663       /// visit a leaf node
0664       void visit(const value_type&) {
0665     (*os_) << "end_branch";
0666     ostream_traits<OStream>::separator(*os_);
0667       }
0668 
0669       /// visit a branching
0670       void visit(const value_type& parent,
0671          const value_type& left, const value_type& right) {
0672     if (first_time_) {
0673       (*os_) << "root_node";
0674       ostream_traits<OStream>::separator(*os_);
0675       parent.put(*os_);
0676       first_time_ = false;
0677     }
0678 
0679     (*os_) << "left_child";
0680     ostream_traits<OStream>::separator(*os_);
0681     left.put(*os_);
0682 
0683     (*os_) << "right_child";
0684     ostream_traits<OStream>::separator(*os_);
0685     right.put(*os_);
0686 
0687       }
0688 
0689     private:
0690 
0691       /// pointer to the ostream to write to
0692       OStream* os_;
0693 
0694       /// whether we are at the or not
0695       bool first_time_;
0696 
0697     };
0698 
0699     /// generator reading binary tree from istream
0700     template<class IStream>
0701     struct istream_generator {
0702 
0703       /// construct from istream reference
0704       explicit istream_generator(IStream& is)
0705     : is_(&is), children_(), tag_("") {}
0706 
0707       /// copy constructor
0708       istream_generator(const istream_generator& x)
0709     : is_(x.is_), children_(), tag_("") {}
0710 
0711       /// read the root node
0712       value_type root() {
0713 
0714     *is_ >> tag_;
0715     assert(tag_ == "root_node");
0716     value_type rnode;
0717     rnode.get(*is_);
0718 
0719     return rnode;
0720       }
0721 
0722       /// read children nodes
0723       bool split() {
0724 
0725     *is_ >> tag_;
0726 
0727     if (tag_ == "end_branch") {
0728       return false;
0729     }
0730 
0731     assert (tag_ == "left_child");
0732     children_.first.get(*is_);
0733 
0734     *is_ >> tag_;
0735     assert(tag_ == "right_child");
0736     children_.second.get(*is_);
0737 
0738     return true;
0739 
0740       }
0741 
0742       /// return the children generated
0743       std::pair<value_type,value_type> generate(const value_type&) {
0744     return children_;
0745       }
0746 
0747       /// initialize a leaf
0748       void initialize_leaf(const value_type&) {}
0749 
0750     private:
0751 
0752       /// pointer to the istream used
0753       IStream* is_;
0754 
0755       /// the children currently handled
0756       std::pair<value_type,value_type> children_;
0757 
0758       /// temporary storage for tags
0759       std::string tag_;
0760 
0761     };
0762 
0763     /// put to ostream
0764     template<class OStream>
0765     void put(OStream& os) const {
0766 
0767       if (empty()) {
0768     os << "empty";
0769     ostream_traits<OStream>::separator(os);
0770     return;
0771       } else if (root() && leaf()) {
0772     os << "root_only";
0773     ostream_traits<OStream>::separator(os);
0774     value().put(os);
0775     return;
0776       } else {
0777     os << "non_empty";
0778     ostream_traits<OStream>::separator(os);
0779       }
0780 
0781       assert(root());
0782       cascade(ostream_visitor<OStream>(os));
0783 
0784     }
0785 
0786     /// get from istream
0787     template<class IStream>
0788     void get(IStream& is) {
0789 
0790       std::string state;
0791       is >> state;
0792 
0793       if (state == "empty") {
0794     return;
0795       }
0796       if (state == "root_only") {
0797     value_.reset(new value_type());
0798     value().get(is);
0799     return;
0800       }
0801 
0802       assert(empty());
0803       generate(istream_generator<IStream>(is));
0804 
0805     }
0806 
0807     //@}
0808 
0809 
0810   private:
0811 
0812     /// calculate hash value
0813     template<class Selector, unsigned long bits>
0814     void do_subtree_hash(const Selector& selector,
0815              bit_container<bits>& current,
0816              unsigned long& position,
0817              bool selected = true) const {
0818 
0819       if (!leaf()) {
0820 
0821     std::pair<bool,bool> which(false,false);
0822     if (selected)
0823       which = selector.use(value(),left_child().value(),right_child().value());
0824 
0825     current.bit(position,which.first);
0826     current.bit(position+1,which.second);
0827 
0828     position += 2;
0829 
0830     left_child().do_subtree_hash(selector,current,position,which.first && selected);
0831     right_child().do_subtree_hash(selector,current,position,which.second && selected);
0832       }
0833 
0834     }
0835 
0836   private:
0837 
0838     ///@name private member access
0839     //@{
0840 
0841     /// return the parent of this node
0842     binary_tree& parent() { assert(parent_); return *parent_; }
0843 
0844     /// return the parent of this node
0845     const binary_tree& parent() const { assert(parent_); return *parent_; }
0846 
0847     /// return the left child of this node
0848     binary_tree& left_child() { assert(children_.first.get()); return *children_.first; }
0849 
0850     /// return the left child of this node
0851     const binary_tree& left_child() const { assert(children_.first.get()); return *children_.first; }
0852 
0853     /// return the right child of this node
0854     binary_tree& right_child() { assert(children_.second.get()); return *children_.second; }
0855 
0856     /// return the right child of this node
0857     const binary_tree& right_child() const { assert(children_.second.get()); return *children_.second; }
0858 
0859     //@}
0860 
0861   private:
0862 
0863     /// the parent of this node
0864     binary_tree * parent_;
0865 
0866     /// the cell held by this node
0867     std::unique_ptr<value_type> value_;
0868 
0869     /// the children of this node
0870     std::pair<std::unique_ptr<binary_tree>,
0871           std::unique_ptr<binary_tree> > children_;
0872 
0873   };
0874 
0875 }
0876 
0877 #endif // EXSAMPLE_binary_tree_h_included