Замените итерацию BGL по вершинам на «чистый»; C ++ 11 альтернатива?

Я хочу заменить итерацию BGL по вершинам или ребрам на чистый эквивалент C ++ 11. Код 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)] << ") ";
}

Я попробовал несколько предложений отсюда: Заменить BOOST_FOREACH на "чистый" C ++ 11 альтернатива? но без удачи.

Я хочу иметь возможность написать что-то вроде:

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)
{...}

Является ли это возможным?

10

Решение

Простая обертка 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))){
// ...
}
8

Другие решения

Boost.Graph также предоставляет удобные макросы, похожие на BOOST_FOREACH, но разработанные специально для итераций Graph.

Итерация по всем вершинам / ребрам данного графа обеспечивается макросами BGL_FORALL_VERTICES / BGL_FORALL_EDGES и их шаблонными аналогами BGL_FORALL_VERTICES_T / BGL_FORALL_EDGES_T.

Итерация по внутренним или внешним сторонам данной вершины обеспечивается макросами BGL_FORALL_OUTEDGES или BGL_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.

3