【问题标题】:Replace BGL iterate over vertexes with "pure" C++11 alternative?用“纯”C++ 11 替代 BGL 迭代顶点?
【发布时间】:2012-11-07 08:21:33
【问题描述】:

我想用纯 C++11 等价物替换顶点或边上的 BGL 迭代。 BGL 代码(来自:http://www.boost.org/doc/libs/1_52_0/libs/graph/doc/quick_tour.html)是:

typename boost::graph_traits<Graph>::out_edge_iterator out_i, out_end;
typename boost::graph_traits<Graph>::edge_descriptor e;
for (std::tie(out_i, out_end) = out_edges(v, g);
     out_i != out_end; ++out_i)
{
  e = *out_i;
  Vertex src = source(e, g), targ = target(e, g);
  std::cout << "(" << name[get(vertex_id, src)]
            << "," << name[get(vertex_id, targ)] << ") ";
}

我从这里尝试了几个建议:Replace BOOST_FOREACH with "pure" C++11 alternative? 但没有运气。

我希望能够写出类似的东西:

for (auto &e : out_edges(v, g))
{ ... }

或类似的东西:

for (std::tie(auto out_i, auto out_end) = out_edges(v, g);
     out_i != out_end; ++out_i)
{...}

有可能吗?

【问题讨论】:

    标签: c++ boost c++11 iterator boost-graph


    【解决方案1】:

    一个简单的out_edges 包装器就足够了:

    #include <boost/range/iterator_range.hpp>
    #include <type_traits>
    
    template<class T> using Invoke = typename T::type
    template<class T> using RemoveRef = Invoke<std::remove_reference<T>>;
    template<class G> using OutEdgeIterator = typename boost::graph_traits<G>::out_edge_iterator;
    
    template<class V, class G>
    auto out_edges_range(V&& v, G&& g)
      -> boost::iterator_range<OutEdgeIterator<RemoveRef<G>>>
    {
      auto edge_pair = out_edges(std::forward<V>(v), std::forward<G>(g));
      return boost::make_iterator_range(edge_pair.first, edge_pair.second);
    }
    

    或者更简单,将std::pair 转换为有效范围的函数:

    template<class It>
    boost::iterator_range<It> pair_range(std::pair<It, It> const& p){
      return boost::make_iterator_range(p.first, p.second);
    }
    

    然后

    for(auto e : pair_range(out_edges(v, g))){
      // ...
    }
    

    【讨论】:

    • 谢谢,但是你提供的代码连编译都没有:(请看源代码(包括你的代码):pastebin.com/Nx7WeMhU
    • 这里是:pastebin.com/LDLRYwNG(另外我在第 20 行添加了 ';',因为没有它会缺少分号语法错误)
    • @danilo2:机器人刚刚修复了我的答案,它在RemoveReference using-alias 中缺少一个简单的&lt;T&gt;
    • 谢谢,现在它可以编译了,但是当这样使用它时: for (auto &e : out_edges_range(v, g)){} 我又遇到了一个错误:pastebin.com/QS5qJQWM
    • @danilo2:我刚刚注意到你在问题中的e 也是一个简单的值——然后就做for(auto e : out_edges_range(v, g))。问题是out_edge_iterators 在取消引用它们时按值返回,它们是所谓的 proxy-iterators
    【解决方案2】:

    Boost.Graph 还提供了类似于 BOOST_FOREACH 的便利宏,但专为 Graph 迭代而设计。

    对给定图的所有顶点/边的迭代由宏BGL_FORALL_VERTICES/BGL_FORALL_EDGES 及其模板对应物BGL_FORALL_VERTICES_T/BGL_FORALL_EDGES_T 提供。

    通过宏BGL_FORALL_OUTEDGESBGL_FORALL_INEDGES 提供对给定顶点的内边或外边的迭代。 (为他们的模板版本添加 _T)。对于邻接顶点使用BGL_FORALL_ADJ

    例子:

    #include <boost/graph/iteration_macros.hpp>
    
    typedef ... Graph;
    Graph g;
    BGL_FORALL_VERTICES(v, g, Graph)  //v is declared here and 
    {                                   //is of type Graph::vertex_descriptor
         BGL_FORALL_OUTEDGES(v, e, g, Graph)  //e is declared as Graph::edge_descriptor
         {
    
         }
    }
    

    这些宏适用于 C++03 和 C++11。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-07
      • 1970-01-01
      • 2012-11-07
      • 2021-07-08
      • 2015-04-24
      相关资源
      最近更新 更多