Ticket #3114: depth_first_search.hpp.patch

File depth_first_search.hpp.patch, 8.6 KB (added by Dave Abrahams, 13 years ago)

Patch that parameter-enables depth_first_search without changes to Boost.Parameter

  • depth_first_search.hpp

     
    2121#include <boost/graph/named_function_params.hpp>
    2222#include <boost/ref.hpp>
    2323#include <boost/implicit_cast.hpp>
     24#include <boost/parameter.hpp>
    2425
    2526#include <vector>
    2627#include <utility>
     
    179180
    180181#endif
    181182
     183
     184    // Infrastructure for computing the color map.  We wouldn't need
     185    // most of this stuff, except the legacy positional interface
     186    // didn't place the index_map parameter before the color map, so
     187    // the index_map is not available to the normal Boost.Parameter
     188    // default computation mechanism.
     189    struct not_specified {};
     190
     191    template <class SpecifiedColorMap, class IndexMap>
     192    struct real_color_map_type_impl
     193    {
     194        typedef SpecifiedColorMap type;
     195    };
     196
     197    template <class IndexMap>
     198    struct real_color_map_type_impl<not_specified,IndexMap>
     199    {
     200        typedef boost::shared_array_property_map<default_color_type, IndexMap> type;
     201    };
     202
     203    // This const-stripping business is due to what is arguably a bug
     204    // in Boost.Parameter.  Parameters that aren't qualified by "out"
     205    // or "in_out" ought to be passed by const reference so that the
     206    // type name (e.g. index_map_type) will be deduced as non-const.
     207    template <class SpecifiedColorMap, class IndexMap>
     208    struct real_color_map_type
     209      : real_color_map_type_impl<
     210           typename remove_const<SpecifiedColorMap>::type,
     211           typename remove_const<IndexMap>::type>
     212    {};
     213
     214    template <class VerticesSizeType, class IndexMap, class SpecifiedColorMap>
     215    SpecifiedColorMap&
     216    get_real_color_map(VerticesSizeType, IndexMap const&, SpecifiedColorMap& color_map)
     217    {
     218        return color_map;
     219    }
     220
     221    template <class VerticesSizeType, class IndexMap>
     222    typename real_color_map_type<not_specified,IndexMap>::type
     223    get_real_color_map(VerticesSizeType n, IndexMap& index_map, not_specified)
     224    {
     225        typedef typename real_color_map_type<not_specified,IndexMap>::type result_type;
     226        return result_type(n, index_map);
     227    }
     228 
    182229  } // namespace detail
    183230
    184   template <class VertexListGraph, class DFSVisitor, class ColorMap>
    185   void
    186   depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color,
    187                      typename graph_traits<VertexListGraph>::vertex_descriptor start_vertex)
     231
     232
     233  // Forward declaration to enable default computation
     234  template <class Visitors = null_visitor>
     235  class dfs_visitor;
     236
     237
     238  // Graphs were never passed as named parameters; probably you want to move this elsewhere.
     239  namespace graph { namespace keywords
    188240  {
     241    BOOST_PARAMETER_NAME(graph)
     242  }}
     243
     244  BOOST_PARAMETER_FUNCTION(
     245      (void),                // 1. parenthesized return type
     246      depth_first_search,    // 2. name of the function template
     247
     248      graph::keywords::tag,          // 3. namespace of tag types
     249
     250      (required (graph, *) )  // 4. one required parameter, and
     251
     252      (optional                //    four optional parameters, with defaults
     253       (in_out(visitor), *, boost::dfs_visitor<>())
     254        // would like to compute default here, but we don't have a vertex_index_map yet.
     255       (in_out(color_map), *, detail::not_specified() )
     256       (root_vertex,
     257        *,
     258        // There are one or more Boost.Parameter bugs that prevent us
     259        // from constraining the type of the root_vertex descriptor
     260        // properly.  Fortunately, no constraint (*) works reasonably well
     261//      *(boost::graph_traits<graph::keywords::tag::graph::_>::vertex_descriptor),
     262        *vertices(graph).first)
     263        (vertex_index_map, *, get(boost::vertex_index,graph))
     264      )
     265  )
     266  {
     267    // See notes above about remove_const
     268    typedef typename remove_const<graph_type>::type VertexListGraph;
     269    typedef typename remove_const<visitor_type>::type DFSVisitor;
     270
    189271    typedef typename graph_traits<VertexListGraph>::vertex_descriptor Vertex;
     272   
     273    // Forcing this conversion here makes up for our inability to
     274    // properly constrain it above.
     275    Vertex start_vertex = root_vertex;
     276   
     277    // Legacy BGL code passes these visitors by value, so we need to
     278    // copy it in order to acquire a mutable visitor.  Should that be
     279    // considered a bug in BGL?
     280    DFSVisitor vis = visitor;
     281
     282    // Get the actual color map to use
     283    typedef typename detail::real_color_map_type<color_map_type, vertex_index_map_type>::type ColorMap;
     284    ColorMap color = detail::get_real_color_map(num_vertices(graph), vertex_index_map, color_map);
     285       
    190286    function_requires<DFSVisitorConcept<DFSVisitor, VertexListGraph> >();
    191287    typedef typename property_traits<ColorMap>::value_type ColorValue;
    192288    typedef color_traits<ColorValue> Color;
    193289
    194290    typename graph_traits<VertexListGraph>::vertex_iterator ui, ui_end;
    195     for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
    196       put(color, *ui, Color::white());       vis.initialize_vertex(*ui, g);
     291    for (tie(ui, ui_end) = vertices(graph); ui != ui_end; ++ui) {
     292      put(color, *ui, Color::white());       vis.initialize_vertex(*ui, graph);
    197293    }
    198294
    199     if (start_vertex != implicit_cast<Vertex>(*vertices(g).first)){ vis.start_vertex(start_vertex, g);
    200       detail::depth_first_visit_impl(g, start_vertex, vis, color,
     295    if (start_vertex != implicit_cast<Vertex>(*vertices(graph).first)){ vis.start_vertex(start_vertex, graph);
     296      detail::depth_first_visit_impl(graph, start_vertex, vis, color,
    201297                                     detail::nontruth2());
    202298    }
    203299
    204     for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
     300    for (tie(ui, ui_end) = vertices(graph); ui != ui_end; ++ui) {
    205301      ColorValue u_color = get(color, *ui);
    206       if (u_color == Color::white()) {       vis.start_vertex(*ui, g);
    207         detail::depth_first_visit_impl(g, *ui, vis, color, detail::nontruth2());
     302      if (u_color == Color::white()) {       vis.start_vertex(*ui, graph);
     303        detail::depth_first_visit_impl(graph, *ui, vis, color, detail::nontruth2());
    208304      }
    209305    }
    210306  }
    211307
    212   template <class VertexListGraph, class DFSVisitor, class ColorMap>
    213   void
    214   depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color)
    215   {
    216     typedef typename boost::graph_traits<VertexListGraph>::vertex_iterator vi;
    217     std::pair<vi, vi> verts = vertices(g);
    218     if (verts.first == verts.second)
    219       return;
    220 
    221     depth_first_search(g, vis, color, *verts.first);
    222   }
    223 
    224   template <class Visitors = null_visitor>
     308  template <class Visitors>
    225309  class dfs_visitor {
    226310  public:
    227311    dfs_visitor() { }
     
    279363  }
    280364  typedef dfs_visitor<> default_dfs_visitor;
    281365
     366namespace detail
     367{
     368  // Help for computing the vertex index map for DFS with legacy
     369  // named_params.  Boost.Parameter could make things easier for us by
     370  // allowing us to explicitly pass boost::parameter::void_ and have
     371  // it treated like the argument wasn't passed at all; then we
     372  // wouldn't have needed this and could have used choose_param.
     373  template <class Graph, class VertexIndex, class ColorMap>
     374  inline VertexIndex const&
     375  get_vertex_index(Graph const&, VertexIndex const& x, ColorMap const&) { return x; }
     376
     377  template <class Graph>
     378  inline typename property_map<Graph, vertex_index_t>::const_type
     379  get_vertex_index(Graph const& graph, error_property_not_found, error_property_not_found)
     380  {
     381      return get(boost::vertex_index,graph);
     382  }
     383}
    282384  // Named Parameter Variant
    283385  template <class VertexListGraph, class P, class T, class R>
    284386  void
     
    290392    if (verts.first == verts.second)
    291393      return;
    292394    using namespace boost::graph::keywords;
    293     typedef bgl_named_params<P, T, R> params_type;
    294     BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params)
    295     depth_first_search
    296       (g,
    297        arg_pack[_visitor | make_dfs_visitor(null_visitor())],
    298        boost::detail::color_map_maker<VertexListGraph, arg_pack_type>::make_map(g, arg_pack),
    299        arg_pack[_root_vertex | *vertices(g).first]
    300       );
     395
     396    depth_first_search(
     397        _graph = g,
     398        _visitor = choose_param(
     399            get_param(params, graph_visitor), make_dfs_visitor(null_visitor())),
     400        _root_vertex = choose_param(
     401            get_param(params, root_vertex_t()), *vertices(g).first),
     402        _color_map = choose_param(
     403            get_param(params, vertex_color), detail::not_specified()),
     404        _vertex_index_map = detail::get_vertex_index(
     405            g, get_param(params, vertex_index_t()), get_param(params, vertex_color))
     406        );
    301407  }
    302408
    303409  template <class IncidenceGraph, class DFSVisitor, class ColorMap>