1.1 --- a/src/include/smart_graph.h Thu May 06 09:26:23 2004 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,614 +0,0 @@
1.4 -// -*- mode:C++ -*-
1.5 -
1.6 -#ifndef HUGO_SMART_GRAPH_H
1.7 -#define HUGO_SMART_GRAPH_H
1.8 -
1.9 -///\ingroup graphs
1.10 -///\file
1.11 -///\brief SmartGraph and SymSmartGraph classes.
1.12 -
1.13 -#include <vector>
1.14 -#include <limits.h>
1.15 -
1.16 -#include "invalid.h"
1.17 -
1.18 -namespace hugo {
1.19 -
1.20 -/// \addtogroup graphs
1.21 -/// @{
1.22 - class SymSmartGraph;
1.23 -
1.24 - ///A smart graph class.
1.25 -
1.26 - ///This is a simple and fast graph implementation.
1.27 - ///It is also quite memory efficient, but at the price
1.28 - ///that <b> it does not support node and edge deletion</b>.
1.29 - ///It conforms to the graph interface documented under
1.30 - ///the description of \ref GraphSkeleton.
1.31 - ///\sa \ref GraphSkeleton.
1.32 - ///
1.33 - ///\todo Some member functions could be \c static.
1.34 - ///\author Alpar Juttner
1.35 - class SmartGraph {
1.36 -
1.37 - struct NodeT
1.38 - {
1.39 - int first_in,first_out;
1.40 - NodeT() : first_in(-1), first_out(-1) {}
1.41 - };
1.42 - struct EdgeT
1.43 - {
1.44 - int head, tail, next_in, next_out;
1.45 - //FIXME: is this necessary?
1.46 - EdgeT() : next_in(-1), next_out(-1) {}
1.47 - };
1.48 -
1.49 - std::vector<NodeT> nodes;
1.50 -
1.51 - std::vector<EdgeT> edges;
1.52 -
1.53 - protected:
1.54 -
1.55 - template <typename Key> class DynMapBase
1.56 - {
1.57 - protected:
1.58 - const SmartGraph* G;
1.59 - public:
1.60 - virtual void add(const Key k) = 0;
1.61 - virtual void erase(const Key k) = 0;
1.62 - DynMapBase(const SmartGraph &_G) : G(&_G) {}
1.63 - virtual ~DynMapBase() {}
1.64 - friend class SmartGraph;
1.65 - };
1.66 -
1.67 - public:
1.68 - template <typename T> class EdgeMap;
1.69 - template <typename T> class EdgeMap;
1.70 -
1.71 - class Node;
1.72 - class Edge;
1.73 -
1.74 - // protected:
1.75 - // HELPME:
1.76 - protected:
1.77 - ///\bug It must be public because of SymEdgeMap.
1.78 - ///
1.79 - mutable std::vector<DynMapBase<Node> * > dyn_node_maps;
1.80 - ///\bug It must be public because of SymEdgeMap.
1.81 - ///
1.82 - mutable std::vector<DynMapBase<Edge> * > dyn_edge_maps;
1.83 -
1.84 - public:
1.85 -
1.86 -
1.87 - class NodeIt;
1.88 - class EdgeIt;
1.89 - class OutEdgeIt;
1.90 - class InEdgeIt;
1.91 -
1.92 - template <typename T> class NodeMap;
1.93 - template <typename T> class EdgeMap;
1.94 -
1.95 - public:
1.96 -
1.97 - SmartGraph() : nodes(), edges() { }
1.98 - SmartGraph(const SmartGraph &_g) : nodes(_g.nodes), edges(_g.edges) { }
1.99 -
1.100 - ~SmartGraph()
1.101 - {
1.102 - for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin();
1.103 - i!=dyn_node_maps.end(); ++i) (**i).G=NULL;
1.104 - for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin();
1.105 - i!=dyn_edge_maps.end(); ++i) (**i).G=NULL;
1.106 - }
1.107 -
1.108 - int nodeNum() const { return nodes.size(); } //FIXME: What is this?
1.109 - int edgeNum() const { return edges.size(); } //FIXME: What is this?
1.110 -
1.111 - ///\bug This function does something different than
1.112 - ///its name would suggests...
1.113 - int maxNodeId() const { return nodes.size(); } //FIXME: What is this?
1.114 - ///\bug This function does something different than
1.115 - ///its name would suggests...
1.116 - int maxEdgeId() const { return edges.size(); } //FIXME: What is this?
1.117 -
1.118 - Node tail(Edge e) const { return edges[e.n].tail; }
1.119 - Node head(Edge e) const { return edges[e.n].head; }
1.120 -
1.121 - Node aNode(OutEdgeIt e) const { return edges[e.n].tail; }
1.122 - Node aNode(InEdgeIt e) const { return edges[e.n].head; }
1.123 -
1.124 - Node bNode(OutEdgeIt e) const { return edges[e.n].head; }
1.125 - Node bNode(InEdgeIt e) const { return edges[e.n].tail; }
1.126 -
1.127 - NodeIt& first(NodeIt& v) const {
1.128 - v=NodeIt(*this); return v; }
1.129 - EdgeIt& first(EdgeIt& e) const {
1.130 - e=EdgeIt(*this); return e; }
1.131 - OutEdgeIt& first(OutEdgeIt& e, const Node v) const {
1.132 - e=OutEdgeIt(*this,v); return e; }
1.133 - InEdgeIt& first(InEdgeIt& e, const Node v) const {
1.134 - e=InEdgeIt(*this,v); return e; }
1.135 -
1.136 -// template< typename It >
1.137 -// It first() const { It e; first(e); return e; }
1.138 -
1.139 -// template< typename It >
1.140 -// It first(Node v) const { It e; first(e,v); return e; }
1.141 -
1.142 - bool valid(Edge e) const { return e.n!=-1; }
1.143 - bool valid(Node n) const { return n.n!=-1; }
1.144 -
1.145 - ///\deprecated Use
1.146 - ///\code
1.147 - /// e=INVALID;
1.148 - ///\endcode
1.149 - ///instead.
1.150 - void setInvalid(Edge &e) { e.n=-1; }
1.151 - ///\deprecated Use
1.152 - ///\code
1.153 - /// e=INVALID;
1.154 - ///\endcode
1.155 - ///instead.
1.156 - void setInvalid(Node &n) { n.n=-1; }
1.157 -
1.158 - template <typename It> It getNext(It it) const
1.159 - { It tmp(it); return next(tmp); }
1.160 -
1.161 - NodeIt& next(NodeIt& it) const {
1.162 - it.n=(it.n+2)%(nodes.size()+1)-1;
1.163 - return it;
1.164 - }
1.165 - OutEdgeIt& next(OutEdgeIt& it) const
1.166 - { it.n=edges[it.n].next_out; return it; }
1.167 - InEdgeIt& next(InEdgeIt& it) const
1.168 - { it.n=edges[it.n].next_in; return it; }
1.169 - EdgeIt& next(EdgeIt& it) const { --it.n; return it; }
1.170 -
1.171 - int id(Node v) const { return v.n; }
1.172 - int id(Edge e) const { return e.n; }
1.173 -
1.174 - Node addNode() {
1.175 - Node n; n.n=nodes.size();
1.176 - nodes.push_back(NodeT()); //FIXME: Hmmm...
1.177 -
1.178 - for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin();
1.179 - i!=dyn_node_maps.end(); ++i) (**i).add(n);
1.180 -
1.181 - return n;
1.182 - }
1.183 -
1.184 - Edge addEdge(Node u, Node v) {
1.185 - Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm...
1.186 - edges[e.n].tail=u.n; edges[e.n].head=v.n;
1.187 - edges[e.n].next_out=nodes[u.n].first_out;
1.188 - edges[e.n].next_in=nodes[v.n].first_in;
1.189 - nodes[u.n].first_out=nodes[v.n].first_in=e.n;
1.190 -
1.191 - for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin();
1.192 - i!=dyn_edge_maps.end(); ++i) (**i).add(e);
1.193 -
1.194 - return e;
1.195 - }
1.196 -
1.197 - void clear() {nodes.clear();edges.clear();}
1.198 -
1.199 - class Node {
1.200 - friend class SmartGraph;
1.201 - template <typename T> friend class NodeMap;
1.202 -
1.203 - friend class Edge;
1.204 - friend class OutEdgeIt;
1.205 - friend class InEdgeIt;
1.206 - friend class SymEdge;
1.207 -
1.208 - protected:
1.209 - int n;
1.210 - friend int SmartGraph::id(Node v) const;
1.211 - Node(int nn) {n=nn;}
1.212 - public:
1.213 - Node() {}
1.214 - Node (Invalid) { n=-1; }
1.215 - bool operator==(const Node i) const {return n==i.n;}
1.216 - bool operator!=(const Node i) const {return n!=i.n;}
1.217 - bool operator<(const Node i) const {return n<i.n;}
1.218 - };
1.219 -
1.220 - class NodeIt : public Node {
1.221 - friend class SmartGraph;
1.222 - public:
1.223 - NodeIt() : Node() { }
1.224 - NodeIt(Invalid i) : Node(i) { }
1.225 - NodeIt(const SmartGraph& G) : Node(G.nodes.size()?0:-1) { }
1.226 - };
1.227 -
1.228 - class Edge {
1.229 - friend class SmartGraph;
1.230 - template <typename T> friend class EdgeMap;
1.231 -
1.232 - //template <typename T> friend class SymSmartGraph::SymEdgeMap;
1.233 - //friend Edge SymSmartGraph::opposite(Edge) const;
1.234 -
1.235 - friend class Node;
1.236 - friend class NodeIt;
1.237 - protected:
1.238 - int n;
1.239 - friend int SmartGraph::id(Edge e) const;
1.240 -
1.241 - Edge(int nn) {n=nn;}
1.242 - public:
1.243 - Edge() { }
1.244 - Edge (Invalid) { n=-1; }
1.245 - bool operator==(const Edge i) const {return n==i.n;}
1.246 - bool operator!=(const Edge i) const {return n!=i.n;}
1.247 - bool operator<(const Edge i) const {return n<i.n;}
1.248 - ///\bug This is a workaround until somebody tells me how to
1.249 - ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
1.250 - int &idref() {return n;}
1.251 - const int &idref() const {return n;}
1.252 - };
1.253 -
1.254 - class EdgeIt : public Edge {
1.255 - friend class SmartGraph;
1.256 - public:
1.257 - EdgeIt(const SmartGraph& G) : Edge(G.edges.size()-1) { }
1.258 - EdgeIt (Invalid i) : Edge(i) { }
1.259 - EdgeIt() : Edge() { }
1.260 - ///\bug This is a workaround until somebody tells me how to
1.261 - ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
1.262 - int &idref() {return n;}
1.263 - };
1.264 -
1.265 - class OutEdgeIt : public Edge {
1.266 - friend class SmartGraph;
1.267 - public:
1.268 - OutEdgeIt() : Edge() { }
1.269 - OutEdgeIt (Invalid i) : Edge(i) { }
1.270 -
1.271 - OutEdgeIt(const SmartGraph& G,const Node v)
1.272 - : Edge(G.nodes[v.n].first_out) {}
1.273 - };
1.274 -
1.275 - class InEdgeIt : public Edge {
1.276 - friend class SmartGraph;
1.277 - public:
1.278 - InEdgeIt() : Edge() { }
1.279 - InEdgeIt (Invalid i) : Edge(i) { }
1.280 - InEdgeIt(const SmartGraph& G,Node v) :Edge(G.nodes[v.n].first_in){}
1.281 - };
1.282 -
1.283 - template <typename T> class NodeMap : public DynMapBase<Node>
1.284 - {
1.285 - std::vector<T> container;
1.286 -
1.287 - public:
1.288 - typedef T ValueType;
1.289 - typedef Node KeyType;
1.290 -
1.291 - NodeMap(const SmartGraph &_G) :
1.292 - DynMapBase<Node>(_G), container(_G.maxNodeId())
1.293 - {
1.294 - G->dyn_node_maps.push_back(this);
1.295 - }
1.296 - NodeMap(const SmartGraph &_G,const T &t) :
1.297 - DynMapBase<Node>(_G), container(_G.maxNodeId(),t)
1.298 - {
1.299 - G->dyn_node_maps.push_back(this);
1.300 - }
1.301 -
1.302 - NodeMap(const NodeMap<T> &m) :
1.303 - DynMapBase<Node>(*m.G), container(m.container)
1.304 - {
1.305 - G->dyn_node_maps.push_back(this);
1.306 - }
1.307 -
1.308 - template<typename TT> friend class NodeMap;
1.309 -
1.310 - ///\todo It can copy between different types.
1.311 - ///
1.312 - template<typename TT> NodeMap(const NodeMap<TT> &m) :
1.313 - DynMapBase<Node>(*m.G)
1.314 - {
1.315 - G->dyn_node_maps.push_back(this);
1.316 - typename std::vector<TT>::const_iterator i;
1.317 - for(typename std::vector<TT>::const_iterator i=m.container.begin();
1.318 - i!=m.container.end();
1.319 - i++)
1.320 - container.push_back(*i);
1.321 - }
1.322 - ~NodeMap()
1.323 - {
1.324 - if(G) {
1.325 - std::vector<DynMapBase<Node>* >::iterator i;
1.326 - for(i=G->dyn_node_maps.begin();
1.327 - i!=G->dyn_node_maps.end() && *i!=this; ++i) ;
1.328 - //if(*i==this) G->dyn_node_maps.erase(i); //FIXME: Way too slow...
1.329 - //A better way to do that: (Is this really important?)
1.330 - if(*i==this) {
1.331 - *i=G->dyn_node_maps.back();
1.332 - G->dyn_node_maps.pop_back();
1.333 - }
1.334 - }
1.335 - }
1.336 -
1.337 - void add(const Node k)
1.338 - {
1.339 - if(k.n>=int(container.size())) container.resize(k.n+1);
1.340 - }
1.341 -
1.342 - void erase(const Node) { }
1.343 -
1.344 - void set(Node n, T a) { container[n.n]=a; }
1.345 - //'T& operator[](Node n)' would be wrong here
1.346 - typename std::vector<T>::reference
1.347 - operator[](Node n) { return container[n.n]; }
1.348 - //'const T& operator[](Node n)' would be wrong here
1.349 - typename std::vector<T>::const_reference
1.350 - operator[](Node n) const { return container[n.n]; }
1.351 -
1.352 - ///\warning There is no safety check at all!
1.353 - ///Using operator = between maps attached to different graph may
1.354 - ///cause serious problem.
1.355 - ///\todo Is this really so?
1.356 - ///\todo It can copy between different types.
1.357 - const NodeMap<T>& operator=(const NodeMap<T> &m)
1.358 - {
1.359 - container = m.container;
1.360 - return *this;
1.361 - }
1.362 - template<typename TT>
1.363 - const NodeMap<T>& operator=(const NodeMap<TT> &m)
1.364 - {
1.365 - std::copy(m.container.begin(), m.container.end(), container.begin());
1.366 - return *this;
1.367 - }
1.368 -
1.369 - void update() {} //Useless for Dynamic Maps
1.370 - void update(T a) {} //Useless for Dynamic Maps
1.371 - };
1.372 -
1.373 - template <typename T> class EdgeMap : public DynMapBase<Edge>
1.374 - {
1.375 - std::vector<T> container;
1.376 -
1.377 - public:
1.378 - typedef T ValueType;
1.379 - typedef Edge KeyType;
1.380 -
1.381 - EdgeMap(const SmartGraph &_G) :
1.382 - DynMapBase<Edge>(_G), container(_G.maxEdgeId())
1.383 - {
1.384 - //FIXME: What if there are empty Id's?
1.385 - //FIXME: Can I use 'this' in a constructor?
1.386 - G->dyn_edge_maps.push_back(this);
1.387 - }
1.388 - EdgeMap(const SmartGraph &_G,const T &t) :
1.389 - DynMapBase<Edge>(_G), container(_G.maxEdgeId(),t)
1.390 - {
1.391 - G->dyn_edge_maps.push_back(this);
1.392 - }
1.393 - EdgeMap(const EdgeMap<T> &m) :
1.394 - DynMapBase<Edge>(*m.G), container(m.container)
1.395 - {
1.396 - G->dyn_edge_maps.push_back(this);
1.397 - }
1.398 -
1.399 - template<typename TT> friend class EdgeMap;
1.400 -
1.401 - ///\todo It can copy between different types.
1.402 - ///
1.403 - template<typename TT> EdgeMap(const EdgeMap<TT> &m) :
1.404 - DynMapBase<Edge>(*m.G)
1.405 - {
1.406 - G->dyn_edge_maps.push_back(this);
1.407 - typename std::vector<TT>::const_iterator i;
1.408 - for(typename std::vector<TT>::const_iterator i=m.container.begin();
1.409 - i!=m.container.end();
1.410 - i++)
1.411 - container.push_back(*i);
1.412 - }
1.413 - ~EdgeMap()
1.414 - {
1.415 - if(G) {
1.416 - std::vector<DynMapBase<Edge>* >::iterator i;
1.417 - for(i=G->dyn_edge_maps.begin();
1.418 - i!=G->dyn_edge_maps.end() && *i!=this; ++i) ;
1.419 - //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow...
1.420 - //A better way to do that: (Is this really important?)
1.421 - if(*i==this) {
1.422 - *i=G->dyn_edge_maps.back();
1.423 - G->dyn_edge_maps.pop_back();
1.424 - }
1.425 - }
1.426 - }
1.427 -
1.428 - void add(const Edge k)
1.429 - {
1.430 - if(k.n>=int(container.size())) container.resize(k.n+1);
1.431 - }
1.432 - void erase(const Edge) { }
1.433 -
1.434 - void set(Edge n, T a) { container[n.n]=a; }
1.435 - //T get(Edge n) const { return container[n.n]; }
1.436 - typename std::vector<T>::reference
1.437 - operator[](Edge n) { return container[n.n]; }
1.438 - typename std::vector<T>::const_reference
1.439 - operator[](Edge n) const { return container[n.n]; }
1.440 -
1.441 - ///\warning There is no safety check at all!
1.442 - ///Using operator = between maps attached to different graph may
1.443 - ///cause serious problem.
1.444 - ///\todo Is this really so?
1.445 - ///\todo It can copy between different types.
1.446 - const EdgeMap<T>& operator=(const EdgeMap<T> &m)
1.447 - {
1.448 - container = m.container;
1.449 - return *this;
1.450 - }
1.451 - template<typename TT>
1.452 - const EdgeMap<T>& operator=(const EdgeMap<TT> &m)
1.453 - {
1.454 - std::copy(m.container.begin(), m.container.end(), container.begin());
1.455 - return *this;
1.456 - }
1.457 -
1.458 - void update() {} //Useless for DynMaps
1.459 - void update(T a) {} //Useless for DynMaps
1.460 - };
1.461 -
1.462 - };
1.463 -
1.464 - ///Graph for bidirectional edges.
1.465 -
1.466 - ///The purpose of this graph structure is to handle graphs
1.467 - ///having bidirectional edges. Here the function \c addEdge(u,v) adds a pair
1.468 - ///of oppositely directed edges.
1.469 - ///There is a new edge map type called
1.470 - ///\ref SymSmartGraph::SymEdgeMap "SymEdgeMap"
1.471 - ///that complements this
1.472 - ///feature by
1.473 - ///storing shared values for the edge pairs. The usual
1.474 - ///\ref GraphSkeleton::EdgeMap "EdgeMap"
1.475 - ///can be used
1.476 - ///as well.
1.477 - ///
1.478 - ///The oppositely directed edge can also be obtained easily
1.479 - ///using \ref opposite.
1.480 - ///\warning It shares the similarity with \ref SmartGraph that
1.481 - ///it is not possible to delete edges or nodes from the graph.
1.482 - //\sa \ref SmartGraph.
1.483 -
1.484 - class SymSmartGraph : public SmartGraph
1.485 - {
1.486 - public:
1.487 - template<typename T> class SymEdgeMap;
1.488 - template<typename T> friend class SymEdgeMap;
1.489 -
1.490 - SymSmartGraph() : SmartGraph() { }
1.491 - SymSmartGraph(const SmartGraph &_g) : SmartGraph(_g) { }
1.492 - ///Adds a pair of oppositely directed edges to the graph.
1.493 - Edge addEdge(Node u, Node v)
1.494 - {
1.495 - Edge e = SmartGraph::addEdge(u,v);
1.496 - SmartGraph::addEdge(v,u);
1.497 - return e;
1.498 - }
1.499 -
1.500 - ///The oppositely directed edge.
1.501 -
1.502 - ///Returns the oppositely directed
1.503 - ///pair of the edge \c e.
1.504 - Edge opposite(Edge e) const
1.505 - {
1.506 - Edge f;
1.507 - f.idref() = e.idref() - 2*(e.idref()%2) + 1;
1.508 - return f;
1.509 - }
1.510 -
1.511 - ///Common data storage for the edge pairs.
1.512 -
1.513 - ///This map makes it possible to store data shared by the oppositely
1.514 - ///directed pairs of edges.
1.515 - template <typename T> class SymEdgeMap : public DynMapBase<Edge>
1.516 - {
1.517 - std::vector<T> container;
1.518 -
1.519 - public:
1.520 - typedef T ValueType;
1.521 - typedef Edge KeyType;
1.522 -
1.523 - SymEdgeMap(const SymSmartGraph &_G) :
1.524 - DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2)
1.525 - {
1.526 - static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.push_back(this);
1.527 - }
1.528 - SymEdgeMap(const SymSmartGraph &_G,const T &t) :
1.529 - DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2,t)
1.530 - {
1.531 - G->dyn_edge_maps.push_back(this);
1.532 - }
1.533 -
1.534 - SymEdgeMap(const SymEdgeMap<T> &m) :
1.535 - DynMapBase<SymEdge>(*m.G), container(m.container)
1.536 - {
1.537 - G->dyn_node_maps.push_back(this);
1.538 - }
1.539 -
1.540 - // template<typename TT> friend class SymEdgeMap;
1.541 -
1.542 - ///\todo It can copy between different types.
1.543 - ///
1.544 -
1.545 - template<typename TT> SymEdgeMap(const SymEdgeMap<TT> &m) :
1.546 - DynMapBase<SymEdge>(*m.G)
1.547 - {
1.548 - G->dyn_node_maps.push_back(this);
1.549 - typename std::vector<TT>::const_iterator i;
1.550 - for(typename std::vector<TT>::const_iterator i=m.container.begin();
1.551 - i!=m.container.end();
1.552 - i++)
1.553 - container.push_back(*i);
1.554 - }
1.555 -
1.556 - ~SymEdgeMap()
1.557 - {
1.558 - if(G) {
1.559 - std::vector<DynMapBase<Edge>* >::iterator i;
1.560 - for(i=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.begin();
1.561 - i!=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.end()
1.562 - && *i!=this; ++i) ;
1.563 - //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow...
1.564 - //A better way to do that: (Is this really important?)
1.565 - if(*i==this) {
1.566 - *i=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.back();
1.567 - static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.pop_back();
1.568 - }
1.569 - }
1.570 - }
1.571 -
1.572 - void add(const Edge k)
1.573 - {
1.574 - if(!k.idref()%2&&k.idref()/2>=int(container.size()))
1.575 - container.resize(k.idref()/2+1);
1.576 - }
1.577 - void erase(const Edge k) { }
1.578 -
1.579 - void set(Edge n, T a) { container[n.idref()/2]=a; }
1.580 - //T get(Edge n) const { return container[n.idref()/2]; }
1.581 - typename std::vector<T>::reference
1.582 - operator[](Edge n) { return container[n.idref()/2]; }
1.583 - typename std::vector<T>::const_reference
1.584 - operator[](Edge n) const { return container[n.idref()/2]; }
1.585 -
1.586 - ///\warning There is no safety check at all!
1.587 - ///Using operator = between maps attached to different graph may
1.588 - ///cause serious problem.
1.589 - ///\todo Is this really so?
1.590 - ///\todo It can copy between different types.
1.591 - const SymEdgeMap<T>& operator=(const SymEdgeMap<T> &m)
1.592 - {
1.593 - container = m.container;
1.594 - return *this;
1.595 - }
1.596 - template<typename TT>
1.597 - const SymEdgeMap<T>& operator=(const SymEdgeMap<TT> &m)
1.598 - {
1.599 - std::copy(m.container.begin(), m.container.end(), container.begin());
1.600 - return *this;
1.601 - }
1.602 -
1.603 - void update() {} //Useless for DynMaps
1.604 - void update(T a) {} //Useless for DynMaps
1.605 -
1.606 - };
1.607 -
1.608 - };
1.609 -
1.610 - /// @}
1.611 -
1.612 -} //namespace hugo
1.613 -
1.614 -
1.615 -
1.616 -
1.617 -#endif //SMART_GRAPH_H