# HG changeset patch # User Alpar Juttner # Date 2008-05-26 14:50:47 # Node ID 2c999941b871df96768c2c31a93507c9634cd288 # Parent b1bd0c2a7f57f6e6baaa3db5ec953c63d1c19805 # Parent c7d30f7810e5aacf3e4576740bc00b4273090dd6 Merge diff --git a/lemon/maps.h b/lemon/maps.h --- a/lemon/maps.h +++ b/lemon/maps.h @@ -1674,15 +1674,6 @@ namespace _maps_bits { - template - struct Identity { - typedef Value argument_type; - typedef Value result_type; - Value operator()(const Value& val) const { - return val; - } - }; - template struct IteratorTraits { typedef typename std::iterator_traits<_Iterator>::value_type Value; @@ -1699,20 +1690,33 @@ /// \brief Writable bool map for logging each \c true assigned element /// - /// A \ref concepts::ReadWriteMap "read-write" bool map for logging + /// A \ref concepts::WriteMap "writable" bool map for logging /// each \c true assigned element, i.e it copies subsequently each /// keys set to \c true to the given iterator. + /// The most important usage of it is storing certain nodes or arcs + /// that were marked \c true by an algorithm. /// - /// \tparam It the type of the Iterator. - /// \tparam Ke the type of the map's Key. The default value should - /// work in most cases. + /// There are several algorithms that provide solutions through bool + /// maps and most of them assign \c true at most once for each key. + /// In these cases it is a natural request to store each \c true + /// assigned elements (in order of the assignment), which can be + /// easily done with StoreBoolMap. + /// + /// The simplest way of using this map is through the storeBoolMap() + /// function. + /// + /// \tparam It The type of the iterator. + /// \tparam Ke The key type of the map. The default value set + /// according to the iterator type should work in most cases. /// /// \note The container of the iterator must contain enough space - /// for the elements. (Or it should be an inserter iterator). - /// - /// \todo Revise the name of this class and give an example code. + /// for the elements or the iterator should be an inserter iterator. +#ifdef DOXYGEN + template +#else template ::Value> +#endif class StoreBoolMap { public: typedef It Iterator; @@ -1735,7 +1739,7 @@ } /// The set function of the map - void set(const Key& key, Value value) const { + void set(const Key& key, Value value) { if (value) { *_end++ = key; } @@ -1743,8 +1747,38 @@ private: Iterator _begin; - mutable Iterator _end; + Iterator _end; }; + + /// Returns a \ref StoreBoolMap class + + /// This function just returns a \ref StoreBoolMap class. + /// + /// The most important usage of it is storing certain nodes or arcs + /// that were marked \c true by an algorithm. + /// For example it makes easier to store the nodes in the processing + /// order of Dfs algorithm, as the following examples show. + /// \code + /// std::vector v; + /// dfs(g,s).processedMap(storeBoolMap(std::back_inserter(v))).run(); + /// \endcode + /// \code + /// std::vector v(countNodes(g)); + /// dfs(g,s).processedMap(storeBoolMap(v.begin())).run(); + /// \endcode + /// + /// \note The container of the iterator must contain enough space + /// for the elements or the iterator should be an inserter iterator. + /// + /// \note StoreBoolMap is just \ref concepts::WriteMap "writable", so + /// it cannot be used when a readable map is needed, for example as + /// \c ReachedMap for Bfs, Dfs and Dijkstra algorithms. + /// + /// \relates StoreBoolMap + template + inline StoreBoolMap storeBoolMap(Iterator it) { + return StoreBoolMap(it); + } /// @} } diff --git a/test/maps_test.cc b/test/maps_test.cc --- a/test/maps_test.cc +++ b/test/maps_test.cc @@ -304,6 +304,28 @@ check(!equalMap(id,cm)[1] && equalMap(id,cm)[2] && !equalMap(id,cm)[3], "Something is wrong with EqualMap"); } + + // StoreBoolMap + { + typedef std::vector vec; + vec v1; + vec v2(10); + StoreBoolMap > map1(std::back_inserter(v1)); + StoreBoolMap map2(v2.begin()); + map1.set(10, false); + map1.set(20, true); map2.set(20, true); + map1.set(30, false); map2.set(40, false); + map1.set(50, true); map2.set(50, true); + map1.set(60, true); map2.set(60, true); + check(v1.size() == 3 && v2.size() == 10 && + v1[0]==20 && v1[1]==50 && v1[2]==60 && v2[0]==20 && v2[1]==50 && v2[2]==60, + "Something is wrong with StoreBoolMap"); + + int i = 0; + for ( StoreBoolMap::Iterator it = map2.begin(); + it != map2.end(); ++it ) + check(v1[i++] == *it, "Something is wrong with StoreBoolMap"); + } return 0; }