/* -*- C++ -*- * lemon/static_map.h - Part of LEMON, a generic C++ optimization library * * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #ifndef LEMON_STATIC_MAP_H #define LEMON_STATIC_MAP_H #include #include #include #include #include #include #include #include /// \ingroup graphmaps /// ///\file ///\brief Static sized graph maps. namespace lemon { /// \ingroup graphmaps /// /// \brief Graph map with static sized storage. /// /// The StaticMap template class is graph map structure what /// does not update automatically the map when a key is added to or /// erased from the map rather it throws an exception. This map factory /// uses the allocators to implement the container functionality. /// /// \param Registry The AlterationNotifier that will notify this map. /// \param Item The item type of the graph items. /// \param Value The value type of the map. /// /// \author Balazs Dezso template class StaticMap : public AlterationNotifier<_Item>::ObserverBase { public: /// \brief Exception class for unsupported exceptions. class UnsupportedOperation : public lemon::LogicError { public: virtual const char* exceptionName() const { return "lemon::StaticMap::UnsupportedOperation"; } }; private: typedef std::vector<_Value> Container; public: /// The graph type of the map. typedef _Graph Graph; /// The reference map tag. typedef True ReferenceMapTag; /// The key type of the map. typedef _Item Key; /// The value type of the map. typedef _Value Value; /// The const reference type of the map. typedef typename Container::const_reference ConstReference; /// The reference type of the map. typedef typename Container::reference Reference; typedef const Value ConstValue; typedef Value* Pointer; typedef const Value* ConstPointer; typedef AlterationNotifier<_Item> Registry; /// The map type. typedef StaticMap Map; /// The base class of the map. typedef typename Registry::ObserverBase Parent; /// \brief Constructor to attach the new map into the registry. /// /// It constructs a map and attachs it into the registry. /// It adds all the items of the graph to the map. StaticMap(const Graph& _g) : graph(&_g) { attach(_g.getNotifier(_Item())); build(); } /// \brief Constructor uses given value to initialize the map. /// /// It constructs a map uses a given value to initialize the map. /// It adds all the items of the graph to the map. StaticMap(const Graph& _g, const Value& _v) : graph(&_g) { attach(_g.getNotifier(_Item())); unsigned size = graph->maxId(_Item()) + 1; container.reserve(size); container.resize(size, _v); } /// \brief Copy constructor /// /// Copy constructor. StaticMap(const StaticMap& _copy) : Parent(), graph(_copy.getGraph()) { if (_copy.attached()) { attach(*_copy.getRegistry()); container = _copy.container; } } /// \brief Destrcutor /// /// Destructor. virtual ~StaticMap() { clear(); if (attached()) { detach(); } } private: StaticMap& operator=(const StaticMap&); protected: using Parent::attach; using Parent::detach; using Parent::attached; const Graph* getGraph() const { return graph; } public: /// \brief The subcript operator. /// /// The subscript operator. The map can be subscripted by the /// actual items of the graph. Reference operator[](const Key& key) { return container[graph->id(key)]; } /// \brief The const subcript operator. /// /// The const subscript operator. The map can be subscripted by the /// actual items of the graph. ConstReference operator[](const Key& key) const { return container[graph->id(key)]; } /// \brief The setter function of the map. /// /// It the same as operator[](key) = value expression. /// void set(const Key& key, const Value& value) { (*this)[key] = value; } protected: /// \brief Adds a new key to the map. /// /// It adds a new key to the map. It called by the observer registry /// and it overrides the add() member function of the observer base. void add(const Key&) { throw UnsupportedOperation(); } /// \brief Erases a key from the map. /// /// Erase a key from the map. It called by the observer registry /// and it overrides the erase() member function of the observer base. void erase(const Key&) { throw UnsupportedOperation(); } /// Buildes the map. /// It buildes the map. It called by the observer registry /// and it overrides the build() member function of the observer base. void build() { int size = graph->maxId(_Item()) + 1; container.reserve(size); container.resize(size); } /// Clear the map. /// It erase all items from the map. It called by the observer registry /// and it overrides the clear() member function of the observer base. void clear() { container.clear(); } private: Container container; const Graph *graph; }; /// \e template class StaticMappableGraphExtender : public _Base { public: typedef StaticMappableGraphExtender<_Base> Graph; typedef _Base Parent; typedef typename Parent::Node Node; typedef typename Parent::NodeIt NodeIt; typedef typename Parent::Edge Edge; typedef typename Parent::EdgeIt EdgeIt; template class NodeMap : public IterableMapExtender > { public: typedef StaticMappableGraphExtender Graph; typedef IterableMapExtender > Parent; NodeMap(const Graph& _g) : Parent(_g) {} NodeMap(const Graph& _g, const _Value& _v) : Parent(_g, _v) {} NodeMap& operator=(const NodeMap& cmap) { return operator=(cmap); } /// \brief Template assign operator. /// /// The given parameter should be conform to the ReadMap /// concecpt and could be indiced by the current item set of /// the NodeMap. In this case the value for each item /// is assigned by the value of the given ReadMap. template NodeMap& operator=(const CMap& cmap) { checkConcept, CMap>(); const typename Parent::Graph* graph = Parent::getGraph(); Node it; for (graph->first(it); it != INVALID; graph->next(it)) { Parent::set(it, cmap[it]); } return *this; } }; template class EdgeMap : public IterableMapExtender > { public: typedef StaticMappableGraphExtender Graph; typedef IterableMapExtender > Parent; EdgeMap(const Graph& _g) : Parent(_g) {} EdgeMap(const Graph& _g, const _Value& _v) : Parent(_g, _v) {} EdgeMap& operator=(const EdgeMap& cmap) { return operator=(cmap); } template EdgeMap& operator=(const CMap& cmap) { checkConcept, CMap>(); const typename Parent::Graph* graph = Parent::getGraph(); Edge it; for (graph->first(it); it != INVALID; graph->next(it)) { Parent::set(it, cmap[it]); } return *this; } }; }; /// \e template class StaticMappableUndirGraphExtender : public StaticMappableGraphExtender<_Base> { public: typedef StaticMappableUndirGraphExtender Graph; typedef StaticMappableGraphExtender<_Base> Parent; typedef typename Parent::UndirEdge UndirEdge; template class UndirEdgeMap : public IterableMapExtender > { public: typedef StaticMappableUndirGraphExtender Graph; typedef IterableMapExtender< StaticMap > Parent; UndirEdgeMap(const Graph& _g) : Parent(_g) {} UndirEdgeMap(const Graph& _g, const _Value& _v) : Parent(_g, _v) {} UndirEdgeMap& operator=(const UndirEdgeMap& cmap) { return operator=(cmap); } template UndirEdgeMap& operator=(const CMap& cmap) { checkConcept, CMap>(); const typename Parent::Graph* graph = Parent::getGraph(); UndirEdge it; for (graph->first(it); it != INVALID; graph->next(it)) { Parent::set(it, cmap[it]); } return *this; } }; }; } #endif