? libs/graph/doc/a.out ? libs/graph/doc/eg1-iso.cpp.patch ? libs/graph/doc/eg1-iso.ii ? libs/graph/doc/eg1-iso.ti ? libs/graph/test/a.out ? boost/pending/property_fixed.hpp Index: boost/graph/adjacency_list.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/graph/adjacency_list.hpp,v retrieving revision 1.35 diff -b -u -r1.35 adjacency_list.hpp --- boost/graph/adjacency_list.hpp 19 May 2003 19:20:18 -0000 1.35 +++ boost/graph/adjacency_list.hpp 7 May 2004 14:57:33 -0000 @@ -46,6 +46,7 @@ #include #include #include +#include namespace boost { @@ -311,21 +312,54 @@ adjacency_list, VertexListS, OutEdgeListS, DirectedS, - VertexProperty, EdgeProperty, GraphProperty, EdgeListS>::type + typename detail::retag_property_list::type, + typename detail::retag_property_list::type, + GraphProperty, EdgeListS>::type { + typedef typename detail::retag_property_list::retagged + maybe_vertex_bundled; + + typedef typename detail::retag_property_list::retagged + maybe_edge_bundled; + + struct no_vertex_bundle {}; + struct no_edge_bundle {}; + + public: + typedef typename detail::retag_property_list::type + vertex_property_type; + typedef typename detail::retag_property_list::type + edge_property_type; + + // The types that are actually bundled + typedef typename ct_if<(is_same::value), + no_vertex_bundle, + maybe_vertex_bundled>::type vertex_bundled; + + typedef typename ct_if<(is_same::value), + no_edge_bundle, + maybe_edge_bundled>::type edge_bundled; + + private: typedef adjacency_list self; typedef typename detail::adj_list_gen< self, VertexListS, OutEdgeListS, DirectedS, - VertexProperty, EdgeProperty, GraphProperty, EdgeListS + vertex_property_type, edge_property_type, GraphProperty, EdgeListS >::type Base; + public: typedef typename Base::stored_vertex stored_vertex; typedef typename Base::vertices_size_type vertices_size_type; typedef typename Base::edges_size_type edges_size_type; typedef typename Base::degree_size_type degree_size_type; + typedef typename Base::vertex_descriptor vertex_descriptor; + typedef typename Base::edge_descriptor edge_descriptor; - typedef EdgeProperty edge_property_type; - typedef VertexProperty vertex_property_type; typedef GraphProperty graph_property_type; inline adjacency_list(const GraphProperty& p = GraphProperty()) @@ -370,6 +404,56 @@ *this = tmp; } + // Directly access a vertex or edge bundle + vertex_bundled& operator[](vertex_descriptor v) + { return get(vertex_bundle, *this)[v]; } + + const vertex_bundled& operator[](vertex_descriptor v) const + { return get(vertex_bundle, *this)[v]; } + + edge_bundled& operator[](edge_descriptor e) + { return get(edge_bundle, *this)[e]; } + + const edge_bundled& operator[](edge_descriptor e) const + { return get(edge_bundle, *this)[e]; } + + // Generate property maps from bundles given a member pointer + template + bundle_property_map + operator->*(T vertex_bundled::* pm) + { + typedef bundle_property_map + result_type; + return result_type(this, pm); + } + + template + bundle_property_map + operator->*(T vertex_bundled::* pm) const + { + typedef bundle_property_map result_type; + return result_type(this, pm); + } + + template + bundle_property_map + operator->*(T edge_bundled::* pm) + { + typedef bundle_property_map + result_type; + return result_type(this, pm); + } + + template + bundle_property_map + operator->*(T edge_bundled::* pm) const + { + typedef bundle_property_map result_type; + return result_type(this, pm); + } + // protected: (would be protected if friends were more portable) GraphProperty m_property; }; Index: boost/graph/graph_test.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/graph/graph_test.hpp,v retrieving revision 1.15 diff -b -u -r1.15 graph_test.hpp Index: boost/graph/properties.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/graph/properties.hpp,v retrieving revision 1.48 diff -b -u -r1.48 properties.hpp --- boost/graph/properties.hpp 7 Mar 2003 16:13:04 -0000 1.48 +++ boost/graph/properties.hpp 7 May 2004 14:57:33 -0000 @@ -113,6 +113,10 @@ BOOST_DEF_PROPERTY(edge, residual_capacity); BOOST_DEF_PROPERTY(graph, visitor); + // For internal use only: these tags are used for property bundles + BOOST_DEF_PROPERTY(vertex, bundle); + BOOST_DEF_PROPERTY(edge, bundle); + #undef BOOST_DEF_PROPERTY namespace detail { @@ -327,6 +331,23 @@ return make_iterator_vertex_map(c.begin()); } + template + struct bundle_property_map + : put_get_helper > + { + typedef Descriptor key_type; + typedef T value_type; + typedef T& reference; + typedef lvalue_property_map_tag category; + + bundle_property_map(Graph* g, T Bundle::* pm) : g(g), pm(pm) {} + + reference operator[](key_type k) const { return (*g)[k].*pm; } + private: + Graph* g; + T Bundle::* pm; + }; + } // namespace boost #endif /* BOOST_GRAPH_PROPERTIES_HPPA */ Index: boost/graph/reverse_graph.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/graph/reverse_graph.hpp,v retrieving revision 1.16 diff -b -u -r1.16 reverse_graph.hpp --- boost/graph/reverse_graph.hpp 15 Jan 2002 03:33:26 -0000 1.16 +++ boost/graph/reverse_graph.hpp 7 May 2004 14:57:34 -0000 @@ -78,6 +78,8 @@ vertex_property_type; typedef reverse_graph_tag graph_tag; + static vertex_descriptor null_vertex() + { return Traits::null_vertex(); } // would be private, but template friends aren't portable enough. // private: Index: libs/graph/doc/adjacency_list.html =================================================================== RCS file: /cvsroot/boost/boost/libs/graph/doc/adjacency_list.html,v retrieving revision 1.31 diff -b -u -r1.31 adjacency_list.html --- libs/graph/doc/adjacency_list.html 3 May 2004 20:03:17 -0000 1.31 +++ libs/graph/doc/adjacency_list.html 7 May 2004 14:57:35 -0000 @@ -177,7 +177,8 @@ Properties . The property maps are objects that implement the interface defined in Section Property Map -Concepts. The property maps obtained from the +Concepts or may be bundled properties, +which have a more succinct syntax. The property maps obtained from the adjacency_list class are models of the Lvalue Property Map concept. If the adjacency_list is const, Index: libs/graph/doc/bundles.html =================================================================== RCS file: libs/graph/doc/bundles.html diff -N libs/graph/doc/bundles.html --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libs/graph/doc/bundles.html 7 May 2004 14:57:35 -0000 @@ -0,0 +1,154 @@ + + + + + Bundled Properties + + + + C++ Boost +

Bundled Properties

+ +

Class template adjacency_list supports + the introduction of named properties via internal + properties. However, this method is cumbersome in many uses, + where it would be more intuitive to just specify a structure or + class that contains internal properties for edges or + vertices. Bundled properties allow one to use + adjacency_list in this manner, providing a simple + way to introduce and access any number of internal properties + for vertices and edges with little effort.

+ +

One can introduce bundled properties into an + adjacency_list by providing a user-defined class + type for the VertexProperties or + EdgeProperties template arguments. The user-defined + class may alternatively be placed at the end of a + property list, replacing the (implicit) + boost::no_property argument.

+ +

Example: Route planning

+

Consider the implementation of a simple route planner that + should find the shortest directions from one city to another + via a set of highways. The vertices of the graph are cities, + and we may wish to store several bits of information about the + city within each vertex:

+
+struct City
+{
+  string name;
+  int population;
+  vector<int> zipcodes;
+};
+      
+ +

The edges in the graph represent highways, which also have + several interesting attributes:

+ +
+struct Highway
+{
+  string name;
+  double miles;
+  int speed_limit;
+  int lanes;
+  bool divided;
+};
+      
+ +

Without bundled properties, translating this example directly + into an instantiation of adjacency_list would + involve several custom properties and would result in a type + like this:

+
+typedef boost::adjacency_list<
+    boost::listS, boost::vecS, boost::bidirectionalS,
+    // Vertex properties
+    boost::property<boost::vertex_name_t, std::string, 
+    boost::property<population_t, int,
+    boost::property<zipcodes_t, std::vector<int> > > >,
+    // Edge properties
+    boost::property<boost::edge_name_t, std::string,
+    boost::property<boost::edge_length_t, double,
+    boost::property<edge_speed_limit_t, int,
+    boost::property<edge_lanes_t, int,
+    boost::property<edge_divided, bool> > > > > >
+  Map;
+      
+ +

With bundled properties, we can directly use the + City and Highway structures:

+
+typedef boost::adjacency_list<
+    boost::listS, boost::vecS, boost::bidirectionalS,
+    City, Highway> Map;
+      
+ +

Accessing bundled properties

+

To access a bundled property for a particular edge or vertex, + subscript your graph with the descriptor of the edge or vertex + whose bundled property you wish to access. For instance:

+
+Map map; // load the map
+Map::vertex_descriptor v = *vertices(map).first;
+map[v].name = "Troy";
+map[v].population = 49170;
+map[v].zipcodes.push_back(12180);
+Map::edge_descriptor e = *out_edges(v, map).first;
+map[e].name = "I-87";
+map[e].miles = 10;
+map[e].speed_limit = 65;
+map[e].lanes = 4;
+map[e].divided = true;
+    
+ +

Properties maps from bundled properties

+

Often one needs to create a property map from an internal + property for use in a generic algorithm. For instance, using the + graph without bundled properties we might invoke Dijkstra's shortest + paths algorithm like this:

+
+vector<double> distances(num_vertices(map));
+dijkstra_shortest_paths(map, from,
+      weight_map(get(edge_length, map))
+      .distance_map(make_iterator_property_map(distances.begin(),
+                                               get(vertex_index, map))));
+    
+ +

With bundled properties, we instead use the overloaded + ->* operator, giving it a pointer to the member + data we wish to use for the property map. The equivalent example + using bundled properties is:

+
+vector<double> distances(num_vertices(map));
+dijkstra_shortest_paths(map, from,
+      weight_map(map->*&Highway::miles)
+      .distance_map(make_iterator_property_map(distances.begin(),
+                                               get(vertex_index, map))));
+    
+ +

Compatibility

Bundled properties will only work + properly on compilers that support class template partial + specialization.

+ +
+Copyright © 2004 Doug Gregor. +
+ + +Last modified: Fri May 7 10:56:01 EDT 2004 + + + Index: libs/graph/test/Jamfile =================================================================== RCS file: /cvsroot/boost/boost/libs/graph/test/Jamfile,v retrieving revision 1.12 diff -b -u -r1.12 Jamfile --- libs/graph/test/Jamfile 5 Feb 2004 20:48:30 -0000 1.12 +++ libs/graph/test/Jamfile 7 May 2004 14:57:35 -0000 @@ -51,6 +51,8 @@ [ compile copy.cpp : $(BOOST_ROOT) ] [ compile property_iter.cpp : $(BOOST_ROOT) ] + + [ run bundled_properties.cpp ] ; # Run SDB tests only when -sSDB= is set. Index: libs/graph/test/bundled_properties.cpp =================================================================== RCS file: libs/graph/test/bundled_properties.cpp diff -N libs/graph/test/bundled_properties.cpp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libs/graph/test/bundled_properties.cpp 7 May 2004 14:57:35 -0000 @@ -0,0 +1,62 @@ +// Boost Graph library + +// Copyright Doug Gregor 2004. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include + +using namespace std; + +struct City +{ + string name; + int population; + vector zipcodes; +}; + +struct Highway +{ + string name; + double miles; + int speed_limit; + int lanes; + bool divided; +}; + +typedef boost::adjacency_list< + boost::listS, boost::vecS, boost::bidirectionalS, + City, Highway> Map; + +int test_main(int, char*[]) +{ + Map map(2); + + Map::vertex_iterator vi = vertices(map).first; + Map::vertex_descriptor v = *vi; + map[v].name = "Troy"; + map[v].population = 49170; + map[v].zipcodes.push_back(12180); + + ++vi; + Map::vertex_descriptor u = *vi; + map[u].name = "Albany"; + map[u].population = 95658; + map[u].zipcodes.push_back(12201); + + Map::edge_descriptor e = add_edge(v, u, map).first; + map[e].name = "I-87"; + map[e].miles = 10; + map[e].speed_limit = 65; + map[e].lanes = 4; + map[e].divided = true; + + BOOST_TEST(get(map->*&City::name, v) == "Troy"); + BOOST_TEST(get(map->*&Highway::name, e) == "I-87"); + + return 0; +} Index: boost/pending/property.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/pending/property.hpp,v retrieving revision 1.15 diff -b -u -r1.15 property.hpp --- boost/pending/property.hpp 17 Feb 2003 07:58:00 -0000 1.15 +++ boost/pending/property.hpp 7 May 2004 14:57:36 -0000 @@ -88,6 +88,41 @@ return Dispatcher::const_get_value(p, t2, tag2); } + namespace detail { +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + template + struct retag_property_list + { + typedef property type; + typedef FinalType retagged; + }; + + template + struct retag_property_list > + { + private: + typedef retag_property_list next; + + public: + typedef property type; + typedef typename next::retagged retagged; + }; + + template + struct retag_property_list + { + typedef no_property type; + typedef no_property retagged; + }; +#else + template + struct retag_property_list + { + typedef Property property; + typedef no_property retagged; + }; +#endif + } } // namesapce boost #endif /* BOOST_PROPERTY_HPP */