Ticket #325: stliteratorsbe9aea8c23ae.patch
File stliteratorsbe9aea8c23ae.patch, 10.6 KB (added by , 7 years ago) 


CMakeLists.txt
# HG changeset patch # User Gabor Gevay <ggab90@gmail.com> # Date 1388957096 3600 # Sun Jan 05 22:24:56 2014 +0100 # Node ID be9aea8c23aef50ccebb617f98c7b541b12cd3f2 # Parent 62dba6c90f359c7a4f713131a5a025c1821d951e Added proof of concept implementation of STL style iterators. (#325) diff git a/CMakeLists.txt b/CMakeLists.txt
a b 246 246 247 247 ENABLE_TESTING() 248 248 249 250 INCLUDE(CheckCXXCompilerFlag) 251 CHECK_CXX_COMPILER_FLAG("std=c++11" CXX11) 252 IF(CXX11) 253 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} std=c++11") 254 ENDIF() 255 256 249 257 IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer") 250 258 ADD_CUSTOM_TARGET(check ALL COMMAND ${CMAKE_CTEST_COMMAND}) 251 259 ELSE() 
contrib/CMakeLists.txt
diff git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt
a b 17 17 # ADD_EXECUTABLE(myprog myprogmain.cc) 18 18 # TARGET_LINK_LIBRARIES(myprog lemon) 19 19 20 21 ADD_EXECUTABLE(stlit_test stlit_test/stlit_test.cc) 22 TARGET_LINK_LIBRARIES(stlit_test lemon) 23 
new file contrib/stlit_test/stlit_test.cc
diff git a/contrib/stlit_test/stlit_test.cc b/contrib/stlit_test/stlit_test.cc new file mode 100755
 + 1 /* * mode: C++; indenttabsmode: nil; * 2 */ 3 4 5 #include <iostream> 6 #include <lemon/list_graph.h> 7 #include <lemon/stl_iterators.h> 8 9 10 using namespace std; 11 using namespace lemon; 12 13 14 /*#include <chrono> 15 using namespace chrono; 16 void speedTest(){ 17 ListDigraph g; 18 const int n=100000; 19 for(int i=0; i<n; i++) 20 g.addNode(); 21 22 23 // //for(ListDigraph::NodeIt u(g); u!=INVALID; ++u) 24 // for(auto u: g.nodeColl()) 25 // cout<<g.id(u)<<endl; 26 27 28 vector<ListDigraph::Node> v(n); 29 30 for(int k=0; k<100000; k++){ 31 int i=0; 32 for(ListDigraph::NodeIt u(g); u!=INVALID; ++u){ 33 //for(auto u: g.nodeColl()){ 34 v[i]=u; 35 i++; 36 } 37 } 38 39 cout<<g.id(v[0])<<endl; 40 }*/ 41 42 43 int main() { 44 45 /*auto t1 = high_resolution_clock::now(); 46 47 speedTest(); 48 49 auto t2 = high_resolution_clock::now(); 50 cout << duration_cast<milliseconds>(t2t1).count() << " milliseconds\n"; 51 return 0; 52 */ 53 54 55 const int n=10; 56 ListDigraph g; 57 for(int i=0; i<n; i++) 58 g.addNode(); 59 60 for(auto u: g.nodeColl()) 61 cout<<g.id(u)<<endl; 62 63 //Test postincrement 64 // for(auto it=g.nodeColl().begin(); it!=g.nodeColl().end(); it++) { 65 // auto u=*it; 66 // cout<<g.id(u)<<endl; 67 // } 68 69 70 71 cout<<endl; 72 73 vector<ListDigraph::Node> v1(n); 74 copy(g.nodeColl().begin(), g.nodeColl().end(), v1.begin()); 75 76 vector<ListDigraph::Node> v(g.nodeColl().begin(), g.nodeColl().end()); 77 g.addArc(v[0],v[1]); 78 g.addArc(v[0],v[2]); 79 80 for(auto e: g.outArcs(v[0])) 81 cout<<g.id(g.target(e))<<endl; 82 83 cout<<endl; 84 85 86 ToStlit<ListDigraph::NodeIt> st1 = g.nodeColl().begin(); 87 //auto st1 = g.nodeColl().begin(); 88 auto st2 = st1; //test assignment 89 ++st1; //test preincrement 90 st1++; //test postincrement 91 cout<<g.id(st1)<<" "<<g.id(st2)<<endl; 92 swap(st1, st2); //test swap 93 cout<<g.id(st1)<<" "<<g.id(st2)<<endl; 94 95 st1>operator==(st2); 96 97 return 0; 98 } 
lemon/bits/graph_extender.h
diff git a/lemon/bits/graph_extender.h b/lemon/bits/graph_extender.h
a b 27 27 #include <lemon/concept_check.h> 28 28 #include <lemon/concepts/maps.h> 29 29 30 #include <lemon/stl_iterators.h> 31 30 32 //\ingroup graphbits 31 33 //\file 32 34 //\brief Extenders for the graph types … … 116 118 117 119 }; 118 120 121 LemonitWrapper1<NodeIt, Digraph> nodeColl() { 122 return LemonitWrapper1<NodeIt, Digraph>(*this); 123 } 119 124 120 125 class ArcIt : public Arc { 121 126 const Digraph* _digraph; … … 163 168 164 169 }; 165 170 171 LemonitWrapper2<OutArcIt, Digraph, Node> outArcs(const Node& u){ 172 return LemonitWrapper2<OutArcIt, Digraph, Node>(*this, u); 173 } 174 166 175 167 176 class InArcIt : public Arc { 168 177 const Digraph* _digraph; 
lemon/concepts/digraph.h
diff git a/lemon/concepts/digraph.h b/lemon/concepts/digraph.h
a b 27 27 #include <lemon/concepts/maps.h> 28 28 #include <lemon/concept_check.h> 29 29 #include <lemon/concepts/graph_components.h> 30 #include <lemon/stl_iterators.h> 30 31 31 32 namespace lemon { 32 33 namespace concepts { … … 147 148 NodeIt& operator++() { return *this; } 148 149 }; 149 150 151 /// \brief Gets the collection of the nodes of the digraph. 152 /// 153 /// This function can be used for iterating on 154 /// the nodes of the digraph. It returns a wrapped NodeIt, which looks 155 /// like an STL container (by having begin() and end()) 156 /// which you can use in rangebased for loops, stl algorithms, etc. 157 /// For example you can write: 158 ///\code 159 /// ListDigraph g; 160 /// for(auto v: g.nodeColl()) 161 /// doSomething(v); 162 /// 163 /// //Using an STL algorithm: 164 /// copy(g.nodeColl().begin(), g.nodeColl().end(), vect.begin()); 165 ///\endcode 166 LemonitWrapper1<NodeIt, Digraph> nodeColl() { 167 return LemonitWrapper1<NodeIt, Digraph>(*this); 168 } 169 150 170 151 171 /// The arc type of the digraph 152 172 … … 237 257 OutArcIt& operator++() { return *this; } 238 258 }; 239 259 260 LemonitWrapper2<OutArcIt, Digraph, Node> outArcs(const Node& u){ 261 return LemonitWrapper2<OutArcIt, Digraph, Node>(*this, u); 262 } 263 264 240 265 /// Iterator class for the incoming arcs of a node. 241 266 242 267 /// This iterator goes trough the \e incoming arcs of a certain node 
new file lemon/stl_iterators.h
diff git a/lemon/stl_iterators.h b/lemon/stl_iterators.h new file mode 100644
 + 1 /* * mode: C++; indenttabsmode: nil; * 2 */ 3 4 #ifndef LEMON_ITERATOR_WRAPPERS_H_ 5 #define LEMON_ITERATOR_WRAPPERS_H_ 6 7 #include <lemon/core.h> 8 9 namespace lemon { 10 11 /// \brief Template to make STL iterators from Lemon iterators. 12 /// 13 /// This template makes an STL iterator from a Lemon iterator 14 /// by adding the missing features. 15 /// It inherits from \c std::iterator to make \c iterator_concept work 16 /// (so that STL algorithms work). 17 /// \c T should be the lemon iterator to be decorated. 18 template<class T> 19 struct ToStlit 20 : public T, public std::iterator<std::input_iterator_tag, T> { 21 22 ToStlit(const T &x) : T(x) {} 23 24 //Lemon iterators don't have operator*, (because they rather 25 //inherit from their "value_type"), 26 //so we add one that just returns the object. 27 const T& operator*() const { 28 return *this; 29 } 30 31 //I can't think of any use case for this with Lemon iterators, 32 //but maybe it should be included for completeness. 33 T* operator>() { 34 return this; 35 } 36 37 //Lemon iterators don't have postincrement. 38 void operator++(int) { 39 T::operator++(); 40 } 41 //We also have to redefine preincrement, because it disappeared 42 //when postincrement was defined. 43 T& operator++() { 44 return T::operator++(); 45 } 46 47 }; 48 49 50 /// \brief A generic wrapper for Lemon iterators for rangebased for loops. 51 /// 52 /// This template can be used to create a class 53 /// that has begin() and end() from a Lemon iterator 54 /// (with a 1parameter constructor) 55 /// to make rangebased for loops and STL algorithms work. 56 /// 57 /// \c LIT is the Lemon iterator that will be wrapped 58 /// \c P is the type of the parameter of the constructor of \c LIT. 59 template<class LIT, class P> 60 class LemonitWrapper1{ 61 const P &_p; 62 typedef ToStlit<LIT> It; 63 public: 64 LemonitWrapper1(const P &p) : _p(p) {} 65 It begin() const { 66 return It(LIT(_p)); 67 } 68 It end() const { 69 return It(lemon::INVALID); 70 } 71 }; 72 73 /* 74 /// \brief Gets the collection of nodes of a graph. 75 /// 76 /// This function can be used for iterating on 77 /// the nodes of a graph. It returns a wrapped NodeIt, which looks like 78 /// an STL container (by having begin() and end()) 79 /// which you can use in rangebased for loops, stl algorithms, etc. 80 /// For example you can write: 81 ///\code 82 /// ListDigraph g; 83 /// for(auto v: nodeColl(g)) 84 /// doSomething(v); 85 /// 86 /// //Using an STL algorithm: 87 /// copy(nodes(g).begin(), nodes(g).end(), vect); 88 ///\endcode 89 template<class GR> 90 LemonitWrapper1<typename GR::NodeIt, GR> nodeColl(const GR &g){ 91 return LemonitWrapper1<typename GR::NodeIt, GR>(g); 92 } 93 */ 94 95 /// \brief A generic wrapper for Lemon iterators for rangebased for loops. 96 /// 97 /// This template can be used to create a class 98 /// that has begin() and end() from a Lemon iterator 99 /// (with a 2parameter constructor) 100 /// to make rangebased for loops and STL algorithms work. 101 /// 102 /// \c LIT is the Lemon iterator that will be wrapped 103 /// \c P1 and \c P2 are the types of the parameters 104 /// of the constructor of \c LIT. 105 template<class LIT, class P1, class P2> 106 class LemonitWrapper2{ 107 const P1 &_p1; 108 const P2 &_p2; 109 typedef ToStlit<LIT> It; 110 public: 111 LemonitWrapper2(const P1 &p1, const P2 &p2) : _p1(p1), _p2(p2) {} 112 It begin() const { 113 return It(LIT(_p1, _p2)); 114 } 115 It end() const { 116 return It(lemon::INVALID); 117 } 118 }; 119 120 /*template<class GR> 121 LemonitWrapper2<typename GR::OutArcIt, GR, typename GR::Node> 122 outArcs(const GR &g, typename GR::Node n){ 123 return LemonitWrapper2<typename GR::OutArcIt, GR, typename GR::Node>(g,n); 124 }*/ 125 126 127 128 129 130 131 /* 132 //This is a variadic template version of LemonitWrapper, 133 //to avoid having separate classes for 1 and 2 parameter versions. 134 //The drawback of this is that it would require a C++11 compiler. 135 136 #include <tuple> 137 138 template<class LIT, class... P> 139 class LemonitWrapper { 140 const std::tuple<const P&...> _p; 141 typedef ToStlit<LIT> It; 142 143 //This is based on http://stackoverflow.com/a/7858971/708357 144 template<int ...> struct Seq {}; 145 template<int N, int ...S> struct Gens : Gens<N1, N1, S...> {}; 146 template<int ...S> struct Gens<0, S...>{ typedef Seq<S...> Type; }; 147 template<int ...S> It callConstr(Seq<S...>) const { 148 return LIT(std::get<S>(_p)...); 149 } 150 public: 151 LemonitWrapper(const P&... p) : _p(p...) {} 152 153 It begin() const { 154 return It(callConstr(typename Gens<sizeof...(P)>::Type())); 155 } 156 It end() const { 157 return It(lemon::INVALID); 158 } 159 }; 160 161 162 template<class GR> 163 LemonitWrapper<typename GR::NodeIt, GR> nodes___var(const GR &g){ 164 return LemonitWrapper<typename GR::NodeIt, GR>(g); 165 } 166 167 template<class GR> 168 LemonitWrapper<typename GR::OutArcIt, GR, typename GR::Node> 169 outArcs___var(const GR &g, typename GR::Node n){ 170 return LemonitWrapper<typename GR::OutArcIt, GR, typename GR::Node>(g,n); 171 } 172 */ 173 174 } 175 176 #endif /* LEMON_ITERATOR_WRAPPERS_H_ */