williamr@2: //======================================================================= williamr@2: // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. williamr@2: // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: //======================================================================= williamr@2: // williamr@2: // Revision History: williamr@2: // 01 April 2001: Modified to use new header. (JMaddock) williamr@2: // williamr@2: #ifndef BOOST_GRAPH_GRAPH_SEARCH_VISITORS_HPP williamr@2: #define BOOST_GRAPH_GRAPH_SEARCH_VISITORS_HPP williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: namespace boost { williamr@2: williamr@2: // This is a bit more convenient than std::numeric_limits because williamr@2: // you don't have to explicitly provide type T. williamr@2: template williamr@2: inline T numeric_limits_max(T) { return (std::numeric_limits::max)(); } williamr@2: williamr@2: //======================================================================== williamr@2: // Event Tags williamr@2: williamr@2: namespace detail { williamr@2: // For partial specialization workaround williamr@2: enum event_visitor_enum williamr@2: { on_no_event_num, williamr@2: on_initialize_vertex_num, on_start_vertex_num, williamr@2: on_discover_vertex_num, on_finish_vertex_num, on_examine_vertex_num, williamr@2: on_examine_edge_num, on_tree_edge_num, on_non_tree_edge_num, williamr@2: on_gray_target_num, on_black_target_num, williamr@2: on_forward_or_cross_edge_num, on_back_edge_num, williamr@2: on_edge_relaxed_num, on_edge_not_relaxed_num, williamr@2: on_edge_minimized_num, on_edge_not_minimized_num williamr@2: }; williamr@2: williamr@2: template williamr@2: struct functor_to_visitor : Visitor williamr@2: { williamr@2: typedef Event event_filter; williamr@2: functor_to_visitor(const Visitor& visitor) : Visitor(visitor) {} williamr@2: }; williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: struct on_no_event { enum { num = detail::on_no_event_num }; }; williamr@2: williamr@2: struct on_initialize_vertex { williamr@2: enum { num = detail::on_initialize_vertex_num }; }; williamr@2: struct on_start_vertex { enum { num = detail::on_start_vertex_num }; }; williamr@2: struct on_discover_vertex { enum { num = detail::on_discover_vertex_num }; }; williamr@2: struct on_examine_vertex { enum { num = detail::on_examine_vertex_num }; }; williamr@2: struct on_finish_vertex { enum { num = detail::on_finish_vertex_num }; }; williamr@2: williamr@2: struct on_examine_edge { enum { num = detail::on_examine_edge_num }; }; williamr@2: struct on_tree_edge { enum { num = detail::on_tree_edge_num }; }; williamr@2: struct on_non_tree_edge { enum { num = detail::on_non_tree_edge_num }; }; williamr@2: struct on_gray_target { enum { num = detail::on_gray_target_num }; }; williamr@2: struct on_black_target { enum { num = detail::on_black_target_num }; }; williamr@2: struct on_forward_or_cross_edge { williamr@2: enum { num = detail::on_forward_or_cross_edge_num }; }; williamr@2: struct on_back_edge { enum { num = detail::on_back_edge_num }; }; williamr@2: williamr@2: struct on_edge_relaxed { enum { num = detail::on_edge_relaxed_num }; }; williamr@2: struct on_edge_not_relaxed { williamr@2: enum { num = detail::on_edge_not_relaxed_num }; }; williamr@2: struct on_edge_minimized { enum { num = detail::on_edge_minimized_num }; }; williamr@2: struct on_edge_not_minimized { williamr@2: enum { num = detail::on_edge_not_minimized_num }; }; williamr@2: williamr@2: struct true_tag { enum { num = true }; }; williamr@2: struct false_tag { enum { num = false }; }; williamr@2: williamr@2: //======================================================================== williamr@2: // base_visitor and null_visitor williamr@2: williamr@2: // needed for MSVC workaround williamr@2: template williamr@2: struct base_visitor { williamr@2: typedef on_no_event event_filter; williamr@2: template williamr@2: void operator()(T, Graph&) { } williamr@2: }; williamr@2: williamr@2: struct null_visitor : public base_visitor { williamr@2: typedef on_no_event event_filter; williamr@2: template williamr@2: void operator()(T, Graph&) { } williamr@2: }; williamr@2: williamr@2: //======================================================================== williamr@2: // The invoke_visitors() function williamr@2: williamr@2: namespace detail { williamr@2: template williamr@2: inline void williamr@2: invoke_dispatch(Visitor& v, T x, Graph& g, true_tag) { williamr@2: v(x, g); williamr@2: } williamr@2: template williamr@2: inline void williamr@2: invoke_dispatch(Visitor&, T, Graph&, false_tag) { } williamr@2: } // namespace detail williamr@2: williamr@2: template williamr@2: inline void williamr@2: invoke_visitors(std::pair& vlist, T x, Graph& g, Tag tag) { williamr@2: typedef typename Visitor::event_filter Category; williamr@2: typedef typename graph_detail::is_same::is_same_tag williamr@2: IsSameTag; williamr@2: detail::invoke_dispatch(vlist.first, x, g, IsSameTag()); williamr@2: invoke_visitors(vlist.second, x, g, tag); williamr@2: } williamr@2: #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 williamr@2: template williamr@2: inline void williamr@2: invoke_visitors(base_visitor& vis, T x, Graph& g, Tag) { williamr@2: typedef typename Visitor::event_filter Category; williamr@2: typedef typename graph_detail::is_same::is_same_tag williamr@2: IsSameTag; williamr@2: Visitor& v = static_cast(vis); williamr@2: detail::invoke_dispatch(v, x, g, IsSameTag()); williamr@2: } williamr@2: #else williamr@2: template williamr@2: inline void williamr@2: invoke_visitors(Visitor& v, T x, Graph& g, Tag) { williamr@2: typedef typename Visitor::event_filter Category; williamr@2: typedef typename graph_detail::is_same::is_same_tag williamr@2: IsSameTag; williamr@2: detail::invoke_dispatch(v, x, g, IsSameTag()); williamr@2: } williamr@2: #endif williamr@2: williamr@2: //======================================================================== williamr@2: // predecessor_recorder williamr@2: williamr@2: template williamr@2: struct predecessor_recorder williamr@2: : public base_visitor > williamr@2: { williamr@2: typedef Tag event_filter; williamr@2: predecessor_recorder(PredecessorMap pa) : m_predecessor(pa) { } williamr@2: template williamr@2: void operator()(Edge e, const Graph& g) { williamr@2: put(m_predecessor, target(e, g), source(e, g)); williamr@2: } williamr@2: PredecessorMap m_predecessor; williamr@2: }; williamr@2: template williamr@2: predecessor_recorder williamr@2: record_predecessors(PredecessorMap pa, Tag) { williamr@2: return predecessor_recorder (pa); williamr@2: } williamr@2: williamr@2: //======================================================================== williamr@2: // edge_predecessor_recorder williamr@2: williamr@2: template williamr@2: struct edge_predecessor_recorder williamr@2: : public base_visitor > williamr@2: { williamr@2: typedef Tag event_filter; williamr@2: edge_predecessor_recorder(PredEdgeMap pa) : m_predecessor(pa) { } williamr@2: template williamr@2: void operator()(Edge e, const Graph& g) { williamr@2: put(m_predecessor, target(e, g), e); williamr@2: } williamr@2: PredEdgeMap m_predecessor; williamr@2: }; williamr@2: template williamr@2: edge_predecessor_recorder williamr@2: record_edge_predecessors(PredEdgeMap pa, Tag) { williamr@2: return edge_predecessor_recorder (pa); williamr@2: } williamr@2: williamr@2: //======================================================================== williamr@2: // distance_recorder williamr@2: williamr@2: template williamr@2: struct distance_recorder williamr@2: : public base_visitor > williamr@2: { williamr@2: typedef Tag event_filter; williamr@2: distance_recorder(DistanceMap pa) : m_distance(pa) { } williamr@2: template williamr@2: void operator()(Edge e, const Graph& g) { williamr@2: typename graph_traits::vertex_descriptor williamr@2: u = source(e, g), v = target(e, g); williamr@2: put(m_distance, v, get(m_distance, u) + 1); williamr@2: } williamr@2: DistanceMap m_distance; williamr@2: }; williamr@2: template williamr@2: distance_recorder williamr@2: record_distances(DistanceMap pa, Tag) { williamr@2: return distance_recorder (pa); williamr@2: } williamr@2: williamr@2: //======================================================================== williamr@2: // time_stamper williamr@2: williamr@2: williamr@2: template williamr@2: struct time_stamper williamr@2: : public base_visitor > williamr@2: { williamr@2: typedef Tag event_filter; williamr@2: time_stamper(TimeMap pa, TimeT& t) : m_time_pa(pa), m_time(t) { } williamr@2: template williamr@2: void operator()(Vertex u, const Graph&) { williamr@2: put(m_time_pa, u, ++m_time); williamr@2: } williamr@2: TimeMap m_time_pa; williamr@2: TimeT& m_time; williamr@2: }; williamr@2: template williamr@2: time_stamper williamr@2: stamp_times(TimeMap pa, TimeT& time_counter, Tag) { williamr@2: return time_stamper(pa, time_counter); williamr@2: } williamr@2: williamr@2: //======================================================================== williamr@2: // property_writer williamr@2: williamr@2: template williamr@2: struct property_writer williamr@2: : public base_visitor > williamr@2: { williamr@2: typedef Tag event_filter; williamr@2: williamr@2: property_writer(PA pa, OutputIterator out) : m_pa(pa), m_out(out) { } williamr@2: williamr@2: template williamr@2: void operator()(T x, Graph&) { *m_out++ = get(m_pa, x); } williamr@2: PA m_pa; williamr@2: OutputIterator m_out; williamr@2: }; williamr@2: template williamr@2: property_writer williamr@2: write_property(PA pa, OutputIterator out, Tag) { williamr@2: return property_writer(pa, out); williamr@2: } williamr@2: williamr@2: #define BOOST_GRAPH_EVENT_STUB(Event,Kind) \ williamr@2: typedef ::boost::Event Event##_type; \ williamr@2: template \ williamr@2: Kind##_visitor, Visitors> > \ williamr@2: do_##Event(Visitor visitor) \ williamr@2: { \ williamr@2: typedef std::pair, \ williamr@2: Visitors> visitor_list; \ williamr@2: typedef Kind##_visitor result_type; \ williamr@2: return result_type(visitor_list(visitor, m_vis)); \ williamr@2: } williamr@2: williamr@2: } /* namespace boost */ williamr@2: williamr@2: #endif