COIN-OR::LEMON - Graph Library

Ticket #325: stl-iterators-be9aea8c23ae.patch

File stl-iterators-be9aea8c23ae.patch, 10.6 KB (added by Gábor Gévay, 11 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  
    246246
    247247ENABLE_TESTING()
    248248
     249
     250INCLUDE(CheckCXXCompilerFlag)
     251CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11)
     252IF(CXX11)
     253  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
     254ENDIF()
     255
     256
    249257IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
    250258  ADD_CUSTOM_TARGET(check ALL COMMAND ${CMAKE_CTEST_COMMAND})
    251259ELSE()
  • contrib/CMakeLists.txt

    diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt
    a b  
    1717# ADD_EXECUTABLE(myprog myprog-main.cc)
    1818# TARGET_LINK_LIBRARIES(myprog lemon)
    1919
     20
     21ADD_EXECUTABLE(stlit_test stlit_test/stlit_test.cc)
     22TARGET_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++; indent-tabs-mode: nil; -*-
     2 */
     3
     4
     5#include <iostream>
     6#include <lemon/list_graph.h>
     7#include <lemon/stl_iterators.h>
     8
     9
     10using namespace std;
     11using namespace lemon;
     12
     13
     14/*#include <chrono>
     15using namespace chrono;
     16void 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
     43int 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>(t2-t1).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  
    2727#include <lemon/concept_check.h>
    2828#include <lemon/concepts/maps.h>
    2929
     30#include <lemon/stl_iterators.h>
     31
    3032//\ingroup graphbits
    3133//\file
    3234//\brief Extenders for the graph types
     
    116118
    117119    };
    118120
     121    LemonitWrapper1<NodeIt, Digraph> nodeColl() {
     122      return LemonitWrapper1<NodeIt, Digraph>(*this);
     123    }
    119124
    120125    class ArcIt : public Arc {
    121126      const Digraph* _digraph;
     
    163168
    164169    };
    165170
     171    LemonitWrapper2<OutArcIt, Digraph, Node> outArcs(const Node& u){
     172      return LemonitWrapper2<OutArcIt, Digraph, Node>(*this, u);
     173    }
     174
    166175
    167176    class InArcIt : public Arc {
    168177      const Digraph* _digraph;
  • lemon/concepts/digraph.h

    diff --git a/lemon/concepts/digraph.h b/lemon/concepts/digraph.h
    a b  
    2727#include <lemon/concepts/maps.h>
    2828#include <lemon/concept_check.h>
    2929#include <lemon/concepts/graph_components.h>
     30#include <lemon/stl_iterators.h>
    3031
    3132namespace lemon {
    3233  namespace concepts {
     
    147148        NodeIt& operator++() { return *this; }
    148149      };
    149150
     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 range-based 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
    150170
    151171      /// The arc type of the digraph
    152172
     
    237257        OutArcIt& operator++() { return *this; }
    238258      };
    239259
     260      LemonitWrapper2<OutArcIt, Digraph, Node> outArcs(const Node& u){
     261        return LemonitWrapper2<OutArcIt, Digraph, Node>(*this, u);
     262      }
     263
     264
    240265      /// Iterator class for the incoming arcs of a node.
    241266
    242267      /// 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++; indent-tabs-mode: nil; -*-
     2 */
     3
     4#ifndef LEMON_ITERATOR_WRAPPERS_H_
     5#define LEMON_ITERATOR_WRAPPERS_H_
     6
     7#include <lemon/core.h>
     8
     9namespace 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 range-based 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 1-parameter constructor)
     55  /// to make range-based 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 range-based 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 range-based 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 2-parameter constructor)
     100  /// to make range-based 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<N-1, N-1, 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_ */