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