Index: depth_first_search.hpp =================================================================== --- depth_first_search.hpp (revision 57455) +++ depth_first_search.hpp (working copy) @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -179,49 +180,132 @@ #endif + + // Infrastructure for computing the color map. We wouldn't need + // most of this stuff, except the legacy positional interface + // didn't place the index_map parameter before the color map, so + // the index_map is not available to the normal Boost.Parameter + // default computation mechanism. + struct not_specified {}; + + template + struct real_color_map_type_impl + { + typedef SpecifiedColorMap type; + }; + + template + struct real_color_map_type_impl + { + typedef boost::shared_array_property_map type; + }; + + // This const-stripping business is due to what is arguably a bug + // in Boost.Parameter. Parameters that aren't qualified by "out" + // or "in_out" ought to be passed by const reference so that the + // type name (e.g. index_map_type) will be deduced as non-const. + template + struct real_color_map_type + : real_color_map_type_impl< + typename remove_const::type, + typename remove_const::type> + {}; + + template + SpecifiedColorMap& + get_real_color_map(VerticesSizeType, IndexMap const&, SpecifiedColorMap& color_map) + { + return color_map; + } + + template + typename real_color_map_type::type + get_real_color_map(VerticesSizeType n, IndexMap& index_map, not_specified) + { + typedef typename real_color_map_type::type result_type; + return result_type(n, index_map); + } + } // namespace detail - template - void - depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color, - typename graph_traits::vertex_descriptor start_vertex) + + + // Forward declaration to enable default computation + template + class dfs_visitor; + + + // Graphs were never passed as named parameters; probably you want to move this elsewhere. + namespace graph { namespace keywords { + BOOST_PARAMETER_NAME(graph) + }} + + BOOST_PARAMETER_FUNCTION( + (void), // 1. parenthesized return type + depth_first_search, // 2. name of the function template + + graph::keywords::tag, // 3. namespace of tag types + + (required (graph, *) ) // 4. one required parameter, and + + (optional // four optional parameters, with defaults + (in_out(visitor), *, boost::dfs_visitor<>()) + // would like to compute default here, but we don't have a vertex_index_map yet. + (in_out(color_map), *, detail::not_specified() ) + (root_vertex, + *, + // There are one or more Boost.Parameter bugs that prevent us + // from constraining the type of the root_vertex descriptor + // properly. Fortunately, no constraint (*) works reasonably well +// *(boost::graph_traits::vertex_descriptor), + *vertices(graph).first) + (vertex_index_map, *, get(boost::vertex_index,graph)) + ) + ) + { + // See notes above about remove_const + typedef typename remove_const::type VertexListGraph; + typedef typename remove_const::type DFSVisitor; + typedef typename graph_traits::vertex_descriptor Vertex; + + // Forcing this conversion here makes up for our inability to + // properly constrain it above. + Vertex start_vertex = root_vertex; + + // Legacy BGL code passes these visitors by value, so we need to + // copy it in order to acquire a mutable visitor. Should that be + // considered a bug in BGL? + DFSVisitor vis = visitor; + + // Get the actual color map to use + typedef typename detail::real_color_map_type::type ColorMap; + ColorMap color = detail::get_real_color_map(num_vertices(graph), vertex_index_map, color_map); + function_requires >(); typedef typename property_traits::value_type ColorValue; typedef color_traits Color; typename graph_traits::vertex_iterator ui, ui_end; - for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { - put(color, *ui, Color::white()); vis.initialize_vertex(*ui, g); + for (tie(ui, ui_end) = vertices(graph); ui != ui_end; ++ui) { + put(color, *ui, Color::white()); vis.initialize_vertex(*ui, graph); } - if (start_vertex != implicit_cast(*vertices(g).first)){ vis.start_vertex(start_vertex, g); - detail::depth_first_visit_impl(g, start_vertex, vis, color, + if (start_vertex != implicit_cast(*vertices(graph).first)){ vis.start_vertex(start_vertex, graph); + detail::depth_first_visit_impl(graph, start_vertex, vis, color, detail::nontruth2()); } - for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { + for (tie(ui, ui_end) = vertices(graph); ui != ui_end; ++ui) { ColorValue u_color = get(color, *ui); - if (u_color == Color::white()) { vis.start_vertex(*ui, g); - detail::depth_first_visit_impl(g, *ui, vis, color, detail::nontruth2()); + if (u_color == Color::white()) { vis.start_vertex(*ui, graph); + detail::depth_first_visit_impl(graph, *ui, vis, color, detail::nontruth2()); } } } - template - void - depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color) - { - typedef typename boost::graph_traits::vertex_iterator vi; - std::pair verts = vertices(g); - if (verts.first == verts.second) - return; - - depth_first_search(g, vis, color, *verts.first); - } - - template + template class dfs_visitor { public: dfs_visitor() { } @@ -279,6 +363,24 @@ } typedef dfs_visitor<> default_dfs_visitor; +namespace detail +{ + // Help for computing the vertex index map for DFS with legacy + // named_params. Boost.Parameter could make things easier for us by + // allowing us to explicitly pass boost::parameter::void_ and have + // it treated like the argument wasn't passed at all; then we + // wouldn't have needed this and could have used choose_param. + template + inline VertexIndex const& + get_vertex_index(Graph const&, VertexIndex const& x, ColorMap const&) { return x; } + + template + inline typename property_map::const_type + get_vertex_index(Graph const& graph, error_property_not_found, error_property_not_found) + { + return get(boost::vertex_index,graph); + } +} // Named Parameter Variant template void @@ -290,14 +392,18 @@ if (verts.first == verts.second) return; using namespace boost::graph::keywords; - typedef bgl_named_params params_type; - BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) - depth_first_search - (g, - arg_pack[_visitor | make_dfs_visitor(null_visitor())], - boost::detail::color_map_maker::make_map(g, arg_pack), - arg_pack[_root_vertex | *vertices(g).first] - ); + + depth_first_search( + _graph = g, + _visitor = choose_param( + get_param(params, graph_visitor), make_dfs_visitor(null_visitor())), + _root_vertex = choose_param( + get_param(params, root_vertex_t()), *vertices(g).first), + _color_map = choose_param( + get_param(params, vertex_color), detail::not_specified()), + _vertex_index_map = detail::get_vertex_index( + g, get_param(params, vertex_index_t()), get_param(params, vertex_color)) + ); } template