| 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 | |
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 |
| 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 | |
| 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 | |
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, |
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()); |
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> |
| 366 | namespace 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 | } |
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 | ); |