src/work/klao/path.h
changeset 619 e09818232531
parent 607 327f7cf13843
child 682 1ea8162ce638
equal deleted inserted replaced
7:028c8c5bdf36 8:2c2be59a6a78
    21   /// @{
    21   /// @{
    22 
    22 
    23 
    23 
    24   //! \brief A structure for representing directed path in a graph.
    24   //! \brief A structure for representing directed path in a graph.
    25   //!
    25   //!
       
    26   //! A structure for representing directed path in a graph.
    26   //! \param Graph The graph type in which the path is.
    27   //! \param Graph The graph type in which the path is.
    27   //! \param DM DebugMode, defaults to DefaultDebugMode.
    28   //! \param DM DebugMode, defaults to DefaultDebugMode.
    28   //! 
    29   //! 
    29   //! In a sense, the path can be treated as a graph, for is has \c NodeIt
    30   //! In a sense, the path can be treated as a graph, for is has \c NodeIt
    30   //! and \c EdgeIt with the same usage. These types converts to the \c Node
    31   //! and \c EdgeIt with the same usage. These types converts to the \c Node
    52 
    53 
    53     /// \brief Subpath constructor.
    54     /// \brief Subpath constructor.
    54     ///
    55     ///
    55     /// Subpath defined by two nodes.
    56     /// Subpath defined by two nodes.
    56     /// \warning It is an error if the two edges are not in order!
    57     /// \warning It is an error if the two edges are not in order!
    57     /// \todo Implement!
    58     DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b) {
    58     DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b);
    59       if( DM::range_check && (!a.valid() || !b.valid) ) {
       
    60 	// FIXME: this check should be more elaborate...
       
    61 	fault("DirPath, subpath ctor: invalid bounding nodes");
       
    62       }
       
    63       gr = P.gr;
       
    64       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
       
    65     }
       
    66 
    59     /// \brief Subpath constructor.
    67     /// \brief Subpath constructor.
    60     ///
    68     ///
    61     /// Subpath defined by two edges. Contains edges in [a,b)
    69     /// Subpath defined by two edges. Contains edges in [a,b)
    62     /// \warning It is an error if the two edges are not in order!
    70     /// \warning It is an error if the two edges are not in order!
    63     /// \todo Implement!
    71     DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b) {
    64     DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b);
    72       if( DM::range_check && (!a.valid() || !b.valid) ) {
       
    73 	// FIXME: this check should be more elaborate...
       
    74 	fault("DirPath, subpath ctor: invalid bounding nodes");
       
    75       }
       
    76       gr = P.gr;
       
    77       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
       
    78     }
    65 
    79 
    66     /// Length of the path.
    80     /// Length of the path.
    67     size_t length() const { return edges.size(); }
    81     size_t length() const { return edges.size(); }
    68     /// Returns whether the path is empty.
    82     /// Returns whether the path is empty.
    69     bool empty() const { return edges.empty(); }
    83     bool empty() const { return edges.empty(); }
    91     ///
   105     ///
    92     /// \sa nth
   106     /// \sa nth
    93     template<typename It>
   107     template<typename It>
    94     It& first(It &i) const { return i=It(*this); }
   108     It& first(It &i) const { return i=It(*this); }
    95 
   109 
    96     /// \brief Initializes node or edge iterator to point to the node or edge
   110     /// \brief Initializes node iterator to point to the node of a given index.
    97     /// of a given index.
   111     NodeIt& nth(NodeIt &i, int n) const {
    98     template<typename It>
       
    99     It& nth(It &i, int n) const {
       
   100       // FIXME: this test should be different for NodeIt and EdgeIt:
       
   101       if( DM::range_check && (n<0 || n>int(length())) )
   112       if( DM::range_check && (n<0 || n>int(length())) )
   102 	fault("DirPath::nth: index out of range");
   113 	fault("DirPath::nth: index out of range");
   103       return i=It(*this, n);
   114       return i=NodeIt(*this, n);
       
   115     }
       
   116 
       
   117     /// \brief Initializes edge iterator to point to the edge of a given index.
       
   118     EdgeIt& nth(EdgeIt &i, int n) const {
       
   119       if( DM::range_check && (n<0 || n>=int(length())) )
       
   120 	fault("DirPath::nth: index out of range");
       
   121       return i=EdgeIt(*this, n);
   104     }
   122     }
   105 
   123 
   106     /// Checks validity of a node or edge iterator.
   124     /// Checks validity of a node or edge iterator.
   107     template<typename It>
   125     template<typename It>
   108     bool valid(const It &i) const { return i.valid(); }
   126     static
       
   127     bool valid(const It &i) { return i.valid(); }
   109 
   128 
   110     /// Steps the given node or edge iterator.
   129     /// Steps the given node or edge iterator.
   111     template<typename It>
   130     template<typename It>
   112     It& next(It &e) const {
   131     static
       
   132     It& next(It &e) {
   113       if( DM::range_check && !e.valid() )
   133       if( DM::range_check && !e.valid() )
   114 	fault("DirPath::next() on invalid iterator");
   134 	fault("DirPath::next() on invalid iterator");
   115       return ++e;
   135       return ++e;
   116     }
   136     }
   117 
   137 
   118     /// \brief Returns node iterator pointing to the head node of the
   138     /// \brief Returns node iterator pointing to the head node of the
   119     /// given edge iterator.
   139     /// given edge iterator.
   120     NodeIt head(const EdgeIt& e) const {
   140     NodeIt head(const EdgeIt& e) const {
       
   141       if( DM::range_check && !e.valid() )
       
   142 	fault("DirPath::head() on invalid iterator");
   121       return NodeIt(*this, e.idx+1);
   143       return NodeIt(*this, e.idx+1);
   122     }
   144     }
   123 
   145 
   124     /// \brief Returns node iterator pointing to the tail node of the
   146     /// \brief Returns node iterator pointing to the tail node of the
   125     /// given edge iterator.
   147     /// given edge iterator.
   126     NodeIt tail(const EdgeIt& e) const {
   148     NodeIt tail(const EdgeIt& e) const {
       
   149       if( DM::range_check && !e.valid() )
       
   150 	fault("DirPath::tail() on invalid iterator");
   127       return NodeIt(*this, e.idx);
   151       return NodeIt(*this, e.idx);
   128     }
   152     }
   129 
   153 
   130 
   154 
   131     /*** Iterator classes ***/
   155     /*** Iterator classes ***/
   168       NodeIt(const DirPath &_p, int _idx = 0) :
   192       NodeIt(const DirPath &_p, int _idx = 0) :
   169 	idx(_idx), p(&_p) { validate(); }
   193 	idx(_idx), p(&_p) { validate(); }
   170 
   194 
   171       bool valid() const { return idx!=-1; }
   195       bool valid() const { return idx!=-1; }
   172 
   196 
   173       operator const GraphEdge& () const {
   197       operator const GraphNode& () const {
   174 	if(idx >= p->length())
   198 	if(idx >= p->length())
   175 	  return p->to();
   199 	  return p->to();
   176 	else if(idx >= 0)
   200 	else if(idx >= 0)
   177 	  return p->gr->tail(p->edges[idx]);
   201 	  return p->gr->tail(p->edges[idx]);
   178 	else
   202 	else
   195      * 
   219      * 
   196      * \ingroup datas
   220      * \ingroup datas
   197      * This class is used to fill a path with edges.
   221      * This class is used to fill a path with edges.
   198      *
   222      *
   199      * You can push new edges to the front and to the back of the path in
   223      * You can push new edges to the front and to the back of the path in
   200      * arbitrary order the you can commit these changes to the graph.
   224      * arbitrary order then you should commit these changes to the graph.
   201      *
   225      *
   202      * Fundamentally, for most "Paths" (classes fulfilling the
   226      * Fundamentally, for most "Paths" (classes fulfilling the
   203      * PathConcept) while the builder is active (after the first modifying
   227      * PathConcept) while the builder is active (after the first modifying
   204      * operation and until the commit()) the original Path is in a
   228      * operation and until the commit()) the original Path is in a
   205      * "transitional" state (operations ot it have undefined result). But
   229      * "transitional" state (operations ot it have undefined result). But
   213     public:
   237     public:
   214       ///\param _P the path you want to fill in.
   238       ///\param _P the path you want to fill in.
   215       ///
   239       ///
   216       Builder(DirPath &_P) : P(_P) {}
   240       Builder(DirPath &_P) : P(_P) {}
   217 
   241 
   218       ///Sets the first node of the path.
   242       /// Sets the starting node of the path.
   219       
   243       
   220       ///Sets the first node of the path. If the path is empty, this
   244       /// Sets the starting node of the path. Edge added to the path
   221       ///function or setTo() have to be called before any call to \ref
   245       /// afterwards have to be incident to this node.
   222       ///pushFront() or \ref pushBack()
   246       /// It should be called iff the path is empty and before any call to
   223       void setFrom(const GraphNode &) {}
   247       /// \ref pushFront() or \ref pushBack()
   224       
   248       void setStart(const GraphNode &) {}
   225       ///Sets the last node of the path.
   249 
   226       
       
   227       ///Sets the last node of the path. If the path is empty, this
       
   228       ///function or setFrom() have to be called before any call of \ref
       
   229       ///pushFront() or \ref pushBack()
       
   230       void setTo(const GraphNode &) {}
       
   231       
       
   232       ///Push a new edge to the front of the path
   250       ///Push a new edge to the front of the path
   233 
   251 
   234       ///Push a new edge to the front of the path.
   252       ///Push a new edge to the front of the path.
   235       ///\sa setTo
   253       ///\sa setStart
   236       void pushFront(const GraphEdge& e) {
   254       void pushFront(const GraphEdge& e) {
   237 	if( DM::consistensy_check && !empty() && P.gr->head(e)!=from() ) {
   255 	if( DM::consistensy_check && !empty() && P.gr->head(e)!=from() ) {
   238 	  fault("DirPath::Builder::pushFront: nonincident edge");
   256 	  fault("DirPath::Builder::pushFront: nonincident edge");
   239 	}
   257 	}
   240 	front.push_back(e);
   258 	front.push_back(e);
   241       }
   259       }
   242 
   260 
   243       ///Push a new edge to the back of the path
   261       ///Push a new edge to the back of the path
   244 
   262 
   245       ///Push a new edge to the back of the path.
   263       ///Push a new edge to the back of the path.
   246       ///\sa setFrom
   264       ///\sa setStart
   247       void pushBack(const GraphEdge& e) {
   265       void pushBack(const GraphEdge& e) {
   248 	if( DM::consistensy_check && !empty() && P.gr->tail(e)!=to() ) {
   266 	if( DM::consistensy_check && !empty() && P.gr->tail(e)!=to() ) {
   249 	  fault("DirPath::Builder::pushBack: nonincident edge");
   267 	  fault("DirPath::Builder::pushBack: nonincident edge");
   250 	}
   268 	}
   251 	back.push_back(e);
   269 	back.push_back(e);
   263 	  front.clear();
   281 	  front.clear();
   264 	  back.clear();
   282 	  back.clear();
   265 	}
   283 	}
   266       }
   284       }
   267 
   285 
   268 //       ///Desctuctor
   286       // FIXME: Hmm, pontosan hogy is kene ezt csinalni?
   269 
   287       // Hogy kenyelmes egy ilyet hasznalni?
   270 //       ///The desctuctor.
   288       void reserve(size_t r) {
   271 //       ///It commit also commit the changes.
   289 	front.reserve(r);
   272 //       ///\todo Is this what we want?
   290 	back.reserve(r);
   273 //  Nope. Let's use commit() explicitly.
   291       }
   274 //       ~Builder() { commit(); }
   292 
       
   293     private:
       
   294       bool empty() {
       
   295 	return front.empty() && back.empty() && P.empty();
       
   296       }
       
   297 
       
   298       GraphNode from() const {
       
   299 	if( ! front.empty() )
       
   300 	  return P.gr->tail(front[front.size()-1]);
       
   301 	else if( ! P.empty() )
       
   302 	  return P.gr->tail(P.edges[0]);
       
   303 	else if( ! back.empty() )
       
   304 	  return P.gr->tail(back[0]);
       
   305 	else
       
   306 	  return INVALID;
       
   307       }
       
   308       GraphNode to() const {
       
   309 	if( ! back.empty() )
       
   310 	  return P.gr->head(back[back.size()-1]);
       
   311 	else if( ! P.empty() )
       
   312 	  return P.gr->head(P.edges[P.length()-1]);
       
   313 	else if( ! front.empty() )
       
   314 	  return P.gr->head(front[0]);
       
   315 	else
       
   316 	  return INVALID;
       
   317       }
       
   318 
       
   319     };
       
   320 
       
   321   };
       
   322 
       
   323 
       
   324 
       
   325 
       
   326 
       
   327 
       
   328 
       
   329 
       
   330 
       
   331 
       
   332   /**********************************************************************/
       
   333 
       
   334 
       
   335   //! \brief A structure for representing undirected path in a graph.
       
   336   //!
       
   337   //! A structure for representing undirected path in a graph. Ie. this is
       
   338   //! a path in a \e directed graph but the edges should not be directed
       
   339   //! forward.
       
   340   //!
       
   341   //! \param Graph The graph type in which the path is.
       
   342   //! \param DM DebugMode, defaults to DefaultDebugMode.
       
   343   //! 
       
   344   //! In a sense, the path can be treated as a graph, for is has \c NodeIt
       
   345   //! and \c EdgeIt with the same usage. These types converts to the \c Node
       
   346   //! and \c Edge of the original graph.
       
   347   //!
       
   348   //! \todo Thoroughfully check all the range and consistency tests.
       
   349   template<typename Graph, typename DM = DefaultDebugMode>
       
   350   class UndirPath {
       
   351   public:
       
   352     typedef typename Graph::Edge GraphEdge;
       
   353     typedef typename Graph::Node GraphNode;
       
   354     class NodeIt;
       
   355     class EdgeIt;
       
   356 
       
   357   protected:
       
   358     const Graph *gr;
       
   359     typedef std::vector<GraphEdge> Container;
       
   360     Container edges;
       
   361 
       
   362   public:
       
   363 
       
   364     /// \param _G The graph in which the path is.
       
   365     ///
       
   366     UndirPath(const Graph &_G) : gr(&_G) {}
       
   367 
       
   368     /// \brief Subpath constructor.
       
   369     ///
       
   370     /// Subpath defined by two nodes.
       
   371     /// \warning It is an error if the two edges are not in order!
       
   372     UndirPath(const UndirPath &P, const NodeIt &a, const NodeIt &b) {
       
   373       if( DM::range_check && (!a.valid() || !b.valid) ) {
       
   374 	// FIXME: this check should be more elaborate...
       
   375 	fault("UndirPath, subpath ctor: invalid bounding nodes");
       
   376       }
       
   377       gr = P.gr;
       
   378       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
       
   379     }
       
   380 
       
   381     /// \brief Subpath constructor.
       
   382     ///
       
   383     /// Subpath defined by two edges. Contains edges in [a,b)
       
   384     /// \warning It is an error if the two edges are not in order!
       
   385     UndirPath(const UndirPath &P, const EdgeIt &a, const EdgeIt &b) {
       
   386       if( DM::range_check && (!a.valid() || !b.valid) ) {
       
   387 	// FIXME: this check should be more elaborate...
       
   388 	fault("UndirPath, subpath ctor: invalid bounding nodes");
       
   389       }
       
   390       gr = P.gr;
       
   391       edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
       
   392     }
       
   393 
       
   394     /// Length of the path.
       
   395     size_t length() const { return edges.size(); }
       
   396     /// Returns whether the path is empty.
       
   397     bool empty() const { return edges.empty(); }
       
   398 
       
   399     /// Resets the path to an empty path.
       
   400     void clear() { edges.clear(); }
       
   401 
       
   402     /// \brief Starting point of the path.
       
   403     ///
       
   404     /// Starting point of the path.
       
   405     /// Returns INVALID if the path is empty.
       
   406     GraphNode from() const {
       
   407       return empty() ? INVALID : gr->tail(edges[0]);
       
   408     }
       
   409     /// \brief End point of the path.
       
   410     ///
       
   411     /// End point of the path.
       
   412     /// Returns INVALID if the path is empty.
       
   413     GraphNode to() const {
       
   414       return empty() ? INVALID : gr->head(edges[length()-1]);
       
   415     }
       
   416 
       
   417     /// \brief Initializes node or edge iterator to point to the first
       
   418     /// node or edge.
       
   419     ///
       
   420     /// \sa nth
       
   421     template<typename It>
       
   422     It& first(It &i) const { return i=It(*this); }
       
   423 
       
   424     /// \brief Initializes node iterator to point to the node of a given index.
       
   425     NodeIt& nth(NodeIt &i, int n) const {
       
   426       if( DM::range_check && (n<0 || n>int(length())) )
       
   427 	fault("UndirPath::nth: index out of range");
       
   428       return i=NodeIt(*this, n);
       
   429     }
       
   430 
       
   431     /// \brief Initializes edge iterator to point to the edge of a given index.
       
   432     EdgeIt& nth(EdgeIt &i, int n) const {
       
   433       if( DM::range_check && (n<0 || n>=int(length())) )
       
   434 	fault("UndirPath::nth: index out of range");
       
   435       return i=EdgeIt(*this, n);
       
   436     }
       
   437 
       
   438     /// Checks validity of a node or edge iterator.
       
   439     template<typename It>
       
   440     static
       
   441     bool valid(const It &i) { return i.valid(); }
       
   442 
       
   443     /// Steps the given node or edge iterator.
       
   444     template<typename It>
       
   445     static
       
   446     It& next(It &e) {
       
   447       if( DM::range_check && !e.valid() )
       
   448 	fault("UndirPath::next() on invalid iterator");
       
   449       return ++e;
       
   450     }
       
   451 
       
   452     /// \brief Returns node iterator pointing to the head node of the
       
   453     /// given edge iterator.
       
   454     NodeIt head(const EdgeIt& e) const {
       
   455       if( DM::range_check && !e.valid() )
       
   456 	fault("UndirPath::head() on invalid iterator");
       
   457       return NodeIt(*this, e.idx+1);
       
   458     }
       
   459 
       
   460     /// \brief Returns node iterator pointing to the tail node of the
       
   461     /// given edge iterator.
       
   462     NodeIt tail(const EdgeIt& e) const {
       
   463       if( DM::range_check && !e.valid() )
       
   464 	fault("UndirPath::tail() on invalid iterator");
       
   465       return NodeIt(*this, e.idx);
       
   466     }
       
   467 
       
   468 
       
   469     /*** Iterator classes ***/
       
   470     class EdgeIt {
       
   471       friend class UndirPath;
       
   472 
       
   473       int idx;
       
   474       const UndirPath *p;
       
   475     public:
       
   476       EdgeIt() {}
       
   477       EdgeIt(Invalid) : idx(-1), p(0) {}
       
   478       EdgeIt(const UndirPath &_p, int _idx = 0) :
       
   479 	idx(_idx), p(&_p) { validate(); }
       
   480 
       
   481       bool valid() const { return idx!=-1; }
       
   482 
       
   483       operator GraphEdge () const {
       
   484 	return valid() ? p->edges[idx] : INVALID;
       
   485       }
       
   486       EdgeIt& operator++() { ++idx; validate(); return *this; }
       
   487 
       
   488       bool operator==(const EdgeIt& e) const { return idx==e.idx; }
       
   489       bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
       
   490       bool operator<(const EdgeIt& e) const { return idx<e.idx; }
       
   491 
       
   492     private:
       
   493       // FIXME: comparison between signed and unsigned...
       
   494       // Jo ez igy? Vagy esetleg legyen a length() int?
       
   495       void validate() { if( size_t(idx) >= p->length() ) idx=-1; }
       
   496     };
       
   497 
       
   498     class NodeIt {
       
   499       friend class UndirPath;
       
   500 
       
   501       int idx;
       
   502       const UndirPath *p;
       
   503     public:
       
   504       NodeIt() {}
       
   505       NodeIt(Invalid) : idx(-1), p(0) {}
       
   506       NodeIt(const UndirPath &_p, int _idx = 0) :
       
   507 	idx(_idx), p(&_p) { validate(); }
       
   508 
       
   509       bool valid() const { return idx!=-1; }
       
   510 
       
   511       operator const GraphNode& () const {
       
   512 	if(idx >= p->length())
       
   513 	  return p->to();
       
   514 	else if(idx >= 0)
       
   515 	  return p->gr->tail(p->edges[idx]);
       
   516 	else
       
   517 	  return INVALID;
       
   518       }
       
   519       NodeIt& operator++() { ++idx; validate(); return *this; }
       
   520 
       
   521       bool operator==(const NodeIt& e) const { return idx==e.idx; }
       
   522       bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
       
   523       bool operator<(const NodeIt& e) const { return idx<e.idx; }
       
   524 
       
   525     private:
       
   526       void validate() { if( size_t(idx) > p->length() ) idx=-1; }
       
   527     };
       
   528 
       
   529     friend class Builder;    
       
   530 
       
   531     /**
       
   532      * \brief Class to build paths
       
   533      * 
       
   534      * \ingroup datas
       
   535      * This class is used to fill a path with edges.
       
   536      *
       
   537      * You can push new edges to the front and to the back of the path in
       
   538      * arbitrary order then you should commit these changes to the graph.
       
   539      *
       
   540      * Fundamentally, for most "Paths" (classes fulfilling the
       
   541      * PathConcept) while the builder is active (after the first modifying
       
   542      * operation and until the commit()) the original Path is in a
       
   543      * "transitional" state (operations ot it have undefined result). But
       
   544      * in the case of UndirPath the original path is unchanged until the
       
   545      * commit. However we don't recomend that you use this feature.
       
   546      */
       
   547     class Builder {
       
   548       UndirPath &P;
       
   549       Container front, back;
       
   550 
       
   551     public:
       
   552       ///\param _P the path you want to fill in.
       
   553       ///
       
   554       Builder(UndirPath &_P) : P(_P) {}
       
   555 
       
   556       /// Sets the starting node of the path.
       
   557       
       
   558       /// Sets the starting node of the path. Edge added to the path
       
   559       /// afterwards have to be incident to this node.
       
   560       /// It should be called iff the path is empty and before any call to
       
   561       /// \ref pushFront() or \ref pushBack()
       
   562       void setStart(const GraphNode &) {}
       
   563 
       
   564       ///Push a new edge to the front of the path
       
   565 
       
   566       ///Push a new edge to the front of the path.
       
   567       ///\sa setStart
       
   568       void pushFront(const GraphEdge& e) {
       
   569 	if( DM::consistensy_check && !empty() && P.gr->head(e)!=from() ) {
       
   570 	  fault("UndirPath::Builder::pushFront: nonincident edge");
       
   571 	}
       
   572 	front.push_back(e);
       
   573       }
       
   574 
       
   575       ///Push a new edge to the back of the path
       
   576 
       
   577       ///Push a new edge to the back of the path.
       
   578       ///\sa setStart
       
   579       void pushBack(const GraphEdge& e) {
       
   580 	if( DM::consistensy_check && !empty() && P.gr->tail(e)!=to() ) {
       
   581 	  fault("UndirPath::Builder::pushBack: nonincident edge");
       
   582 	}
       
   583 	back.push_back(e);
       
   584       }
       
   585 
       
   586       ///Commit the changes to the path.
       
   587       void commit() {
       
   588 	if( !(front.empty() && back.empty()) ) {
       
   589 	  Container tmp;
       
   590 	  tmp.reserve(front.size()+back.size()+P.length());
       
   591 	  tmp.insert(tmp.end(), front.rbegin(), front.rend());
       
   592 	  tmp.insert(tmp.end(), P.edges.begin(), P.edges.end());
       
   593 	  tmp.insert(tmp.end(), back.begin(), back.end());
       
   594 	  P.edges.swap(tmp);
       
   595 	  front.clear();
       
   596 	  back.clear();
       
   597 	}
       
   598       }
   275 
   599 
   276       // FIXME: Hmm, pontosan hogy is kene ezt csinalni?
   600       // FIXME: Hmm, pontosan hogy is kene ezt csinalni?
   277       // Hogy kenyelmes egy ilyet hasznalni?
   601       // Hogy kenyelmes egy ilyet hasznalni?
   278       void reserve(size_t r) {
   602       void reserve(size_t r) {
   279 	front.reserve(r);
   603 	front.reserve(r);