1 | <HTML> |
---|
2 | <!-- |
---|
3 | -- Copyright (c) Jeremy Siek 2000 |
---|
4 | -- |
---|
5 | -- Permission to use, copy, modify, distribute and sell this software |
---|
6 | -- and its documentation for any purpose is hereby granted without fee, |
---|
7 | -- provided that the above copyright notice appears in all copies and |
---|
8 | -- that both that copyright notice and this permission notice appear |
---|
9 | -- in supporting documentation. Silicon Graphics makes no |
---|
10 | -- representations about the suitability of this software for any |
---|
11 | -- purpose. It is provided "as is" without express or implied warranty. |
---|
12 | --> |
---|
13 | <Head> |
---|
14 | <Title>Property Map Library</Title> |
---|
15 | <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b" |
---|
16 | ALINK="#ff0000"> |
---|
17 | <IMG SRC="../../boost.png" |
---|
18 | ALT="C++ Boost" width="277" height="86"> |
---|
19 | |
---|
20 | <BR Clear> |
---|
21 | |
---|
22 | <H1><A NAME="sec:property-maps"></A> |
---|
23 | Boost Property Map Library |
---|
24 | </H1> |
---|
25 | |
---|
26 | <p>The Boost Property Map Library consists mainly of interface |
---|
27 | specifications in the form of concepts (similar to the iterator |
---|
28 | concepts in the STL <a |
---|
29 | href="http://www.sgi.com/tech/stl/stl_introduction.html">[2]</a>). |
---|
30 | These interface specifications are intended for use by implementors of |
---|
31 | generic libraries in communicating requirements on template parameters |
---|
32 | to their users. In particular, the Boost Property Map concepts define |
---|
33 | a general purpose interface for mapping key objects to corresponding |
---|
34 | value objects, thereby hiding the details of how the mapping is |
---|
35 | implemented from algorithms. The implementation of types fulfilling |
---|
36 | the property map interface is up to the client of the algorithm to |
---|
37 | provide. The property map requirements are purposefully vague on the |
---|
38 | type of the key and value objects to allow for the utmost genericity |
---|
39 | in the function templates of the generic library. |
---|
40 | </p> |
---|
41 | |
---|
42 | <p> |
---|
43 | The need for the property map interface came from the <a |
---|
44 | href="../graph/doc/index.html">Boost Graph Library</a> (BGL), which |
---|
45 | contains many examples of algorithms that use the property map |
---|
46 | concepts to specify their interface. For an example, note the |
---|
47 | <tt>ColorMap</tt> template parameter of the <a |
---|
48 | href="../graph/doc/breadth_first_search.html"> |
---|
49 | <tt>breadth_first_search</tt></a>. In addition, the BGL contains many |
---|
50 | examples of concrete types that implement the property map interface. |
---|
51 | The <a href="../graph/doc/adjacency_list.html"> |
---|
52 | <tt>adjacency_list</tt></a> class implements property maps for |
---|
53 | accessing objects (properties) that are attached to vertices and edges |
---|
54 | of the graph. |
---|
55 | </p> |
---|
56 | |
---|
57 | <p> |
---|
58 | The Boost Property Map Library also contains a <a |
---|
59 | href="#sec:property-map-types"> few adaptors</a> that convert commonly |
---|
60 | used data-structures that implement a mapping operation, such as |
---|
61 | builtin arrays (pointers), iterators, and <a |
---|
62 | href="http://www.sgi.com/tech/stl/Map.html"> <tt>std::map</tt></a>, to |
---|
63 | have the property map interface. These adaptors are not meant to |
---|
64 | fulfill all mapping needs, but are to serve as an example of how to |
---|
65 | implement the interface as well as covering a few common cases. See |
---|
66 | the header files for details. |
---|
67 | </p> |
---|
68 | |
---|
69 | <p>Property maps are statically-typed entities. If you need to access |
---|
70 | property maps in a more dynamic setting (e.g., because you're reading |
---|
71 | an unknown set of attributes from a file), you can use the <a |
---|
72 | href="doc/dynamic_property_map.html"><code>dynamic_properties</code></a> |
---|
73 | class to access a set of property maps through a dynamically-typed |
---|
74 | interface. </p> |
---|
75 | |
---|
76 | <h2><A NAME="sec:property-map-concepts"></A> |
---|
77 | Property Map Concepts |
---|
78 | </h2> |
---|
79 | |
---|
80 | The property map interface consists of a set of concepts (see |
---|
81 | definition of "concept" in <a |
---|
82 | href="../concept_check/concept_check.htm#introduction">[1]</a> and <a |
---|
83 | href="http://www.sgi.com/tech/stl/stl_introduction.html">[2]</a>) that |
---|
84 | define a syntax for mapping key objects to corresponding value |
---|
85 | objects. Since the property map operations are global functions |
---|
86 | (actually they don't have to be global, but they are always called |
---|
87 | unqualified and may be found via argument dependent lookup), it is |
---|
88 | possible to overload the map functions such that nearly arbitrary |
---|
89 | property map types and key types can be used. The interface for |
---|
90 | property maps consists of three functions: <tt>get()</tt>, |
---|
91 | <tt>put()</tt>, and <tt>operator[]</tt>. The following concrete |
---|
92 | example from <a href="./example1.cpp">example1.cpp</a> shows how the |
---|
93 | three functions could be used to access the addresses associated with |
---|
94 | various people. We use a separate function template here to highlight |
---|
95 | the parts of the program that use the property map concept |
---|
96 | interface. In the <tt>main()</tt> function we use <tt>std::map</tt> |
---|
97 | and <tt>boost::associative_property_map</tt>, but it would have been |
---|
98 | OK to use any type (including a custom type that you create) that |
---|
99 | fulfills the property map requirements. |
---|
100 | |
---|
101 | <pre>#include <iostream> |
---|
102 | #include <map> |
---|
103 | #include <string> |
---|
104 | #include <boost/property_map.hpp> |
---|
105 | |
---|
106 | |
---|
107 | template <typename AddressMap> |
---|
108 | void foo(AddressMap address) |
---|
109 | { |
---|
110 | typedef typename boost::property_traits<AddressMap>::value_type value_type; |
---|
111 | typedef typename boost::property_traits<AddressMap>::key_type key_type; |
---|
112 | |
---|
113 | value_type old_address, new_address; |
---|
114 | key_type fred = "Fred"; |
---|
115 | old_address = get(address, fred); |
---|
116 | new_address = "384 Fitzpatrick Street"; |
---|
117 | put(address, fred, new_address); |
---|
118 | |
---|
119 | key_type joe = "Joe"; |
---|
120 | value_type& joes_address = address[joe]; |
---|
121 | joes_address = "325 Cushing Avenue"; |
---|
122 | } |
---|
123 | |
---|
124 | int |
---|
125 | main() |
---|
126 | { |
---|
127 | std::map<std::string, std::string> name2address; |
---|
128 | boost::associative_property_map< std::map<std::string, std::string> > |
---|
129 | address_map(name2address); |
---|
130 | |
---|
131 | name2address.insert(make_pair(std::string("Fred"), |
---|
132 | std::string("710 West 13th Street"))); |
---|
133 | name2address.insert(make_pair(std::string("Joe"), |
---|
134 | std::string("710 West 13th Street"))); |
---|
135 | |
---|
136 | foo(address_map); |
---|
137 | |
---|
138 | for (std::map<std::string, std::string>::iterator i = name2address.begin(); |
---|
139 | i != name2address.end(); ++i) |
---|
140 | std::cout << i->first << ": " << i->second << "\n"; |
---|
141 | |
---|
142 | return EXIT_SUCCESS; |
---|
143 | }</pre> |
---|
144 | |
---|
145 | <p> |
---|
146 | For each property map object there is a set of <i>valid keys</i> |
---|
147 | for which the mapping to value objects is defined. Invoking a |
---|
148 | property map function on an <i>invalid</i> key results in |
---|
149 | undefined behavior. The property map concepts do not specify how |
---|
150 | this set of valid keys is created or modified. A function that uses a |
---|
151 | property map must specify the expected set of valid keys in its |
---|
152 | preconditions. |
---|
153 | |
---|
154 | <p> |
---|
155 | The need for property maps came out of the design of the Boost |
---|
156 | Graph Library, whose algorithms needed an interface for accessing |
---|
157 | properties attached to vertices and edges in a graph. In this context |
---|
158 | the vertex and edge descriptors are the key type of the property |
---|
159 | maps. |
---|
160 | |
---|
161 | <!-- historical note about Decorators and Data Maps --> |
---|
162 | |
---|
163 | <P> |
---|
164 | Several categories of property maps provide |
---|
165 | different access capabilities: |
---|
166 | <DL> |
---|
167 | <DT><STRONG>readable</STRONG></DT> |
---|
168 | <DD>The associated property data can only be read. |
---|
169 | The data is returned by-value. Many property maps defining the |
---|
170 | problem input (such as edge weight) can be defined as readable |
---|
171 | property maps. |
---|
172 | |
---|
173 | <P> |
---|
174 | </DD> |
---|
175 | <DT><STRONG>writeable</STRONG></DT> |
---|
176 | <DD>The associated property can only be written to. |
---|
177 | The parent array used to record the paths in a bread-first search tree |
---|
178 | is an example of a property map that would be defined writeable. |
---|
179 | |
---|
180 | <P> |
---|
181 | </DD> |
---|
182 | <DT><STRONG>read/write</STRONG></DT> |
---|
183 | <DD>The associated property can both be written and read. |
---|
184 | The distance property use in Dijkstra's shortest paths algorithm |
---|
185 | would need to provide both read and write capabilities. |
---|
186 | |
---|
187 | <P> |
---|
188 | </DD> |
---|
189 | <DT><STRONG>lvalue</STRONG></DT> |
---|
190 | <DD>The associated property is actually represented in |
---|
191 | memory and it is possible to get a reference to it. |
---|
192 | The property maps in the lvalue |
---|
193 | category also support the requirements for read/write property |
---|
194 | maps. |
---|
195 | |
---|
196 | <P> |
---|
197 | </DD> |
---|
198 | </DL> |
---|
199 | |
---|
200 | <P> |
---|
201 | There is a separate concept defined for each of the four property |
---|
202 | map categories. These property map concepts are listed |
---|
203 | below, with links to the documentation for each of them. |
---|
204 | |
---|
205 | <ul> |
---|
206 | <li><a href="./ReadablePropertyMap.html">ReadablePropertyMap</a></li> |
---|
207 | <li><a href="./WritablePropertyMap.html">WritablePropertyMap</a></li> |
---|
208 | <li><a href="./ReadWritePropertyMap.html">ReadWritePropertyMap</a></li> |
---|
209 | <li><a href="./LvaluePropertyMap.html">LvaluePropertyMap</a></li> |
---|
210 | </ul> |
---|
211 | |
---|
212 | <h2><a name="sec:property-map-tags">Property Map Category Tags</a></h2> |
---|
213 | |
---|
214 | <P> |
---|
215 | There is a tag struct for each of the categories of property |
---|
216 | maps, which is defined in the header |
---|
217 | <tt><boost/property_map.hpp></tt>. |
---|
218 | |
---|
219 | <PRE>namespace boost { |
---|
220 | |
---|
221 | struct readable_property_map_tag { }; |
---|
222 | |
---|
223 | struct writable_property_map_tag { }; |
---|
224 | |
---|
225 | struct read_write_property_map_tag : |
---|
226 | public readable_property_map_tag, |
---|
227 | public writable_property_map_tag { }; |
---|
228 | |
---|
229 | struct lvalue_property_map_tag : |
---|
230 | public read_write_property_map_tag { }; |
---|
231 | |
---|
232 | }</PRE> |
---|
233 | |
---|
234 | <h2><a name="sec:property-map-traits">Property Map Traits</a></h2> |
---|
235 | |
---|
236 | <P> |
---|
237 | Similar to the <TT>std::iterator_traits</TT> class of the STL, there |
---|
238 | is a <TT>boost::property_traits</TT> class that can be used to deduce |
---|
239 | the types associated with a property map type: the key and value |
---|
240 | types, and the property map category. There is a specialization |
---|
241 | of <TT>boost::property_traits</TT> so that pointers can be used as |
---|
242 | property map objects. In addition, the property map |
---|
243 | functions are overloaded for pointers. These traits classes and |
---|
244 | functions are defined in <tt><boost/property_map.hpp></tt>. |
---|
245 | |
---|
246 | <PRE>namespace boost { |
---|
247 | |
---|
248 | template <typename PropertyMap> |
---|
249 | struct property_traits { |
---|
250 | typedef typename PropertyMap::key_type key_type; |
---|
251 | typedef typename PropertyMap::value_type value_type; |
---|
252 | typedef typename PropertyMap::category category; |
---|
253 | }; |
---|
254 | |
---|
255 | }</PRE> |
---|
256 | |
---|
257 | <h2><a name="sec:property-map-types">Property Map Types</a></h2> |
---|
258 | |
---|
259 | <ul> |
---|
260 | <li>Builtin C++ pointer types.<br> |
---|
261 | |
---|
262 | The following specialization of the <tt>property_traits</tt> class |
---|
263 | and the overloads of <tt>put()</tt> and <tt>get()</tt> make it |
---|
264 | possible to use builtin C++ pointer types as property maps. These |
---|
265 | are defined in <tt>boost/property_map.hpp</tt>. More specifically, |
---|
266 | it means that <tt>T*</tt> is a model of <a |
---|
267 | href="./LvaluePropertyMap.html">LvaluePropertyMap</a>, given a key |
---|
268 | type that is at least convertible <tt>std::ptrdiff_t</tt>. |
---|
269 | |
---|
270 | <PRE>namespace boost { |
---|
271 | // specialization for using pointers as property maps |
---|
272 | template <typename T> |
---|
273 | struct property_traits<T*> { |
---|
274 | typedef T value_type; |
---|
275 | typedef std::ptrdiff_t key_type; |
---|
276 | typedef random_access_iterator_pa_tag category; |
---|
277 | }; |
---|
278 | |
---|
279 | // overloads of the property map functions for pointers |
---|
280 | template<> |
---|
281 | void put(T* pmap, std::ptrdiff_t k, const T& val) { pmap[k] = val; } |
---|
282 | |
---|
283 | template<> |
---|
284 | const T& get(const T* pmap, std::ptrdiff_t k) { return pmap[k]; } |
---|
285 | |
---|
286 | }</PRE> |
---|
287 | </li> |
---|
288 | <li><a href="./identity_property_map.html">identity_property_map</a> </li> |
---|
289 | <li><a href="./iterator_property_map.html">iterator_property_map</a></li> |
---|
290 | <li><a href="./associative_property_map.html">associative_property_map</a></li> |
---|
291 | <li><a href="./const_assoc_property_map.html">const_associative_property_map</a></li> |
---|
292 | <li><a href="./vector_property_map.html">vector_property_map</a></li> |
---|
293 | </ul> |
---|
294 | |
---|
295 | <h3>History</h3> |
---|
296 | |
---|
297 | The property map interface originated as <i>data accessors</i> in |
---|
298 | Dietmar Kühl's Masters Thesis on generic graph algorithms. The |
---|
299 | property map idea also appeared under the guise of <i>decorators</i> |
---|
300 | in early versions of the Generic Graph Component Library (GGCL), which |
---|
301 | is now the Boost Graph Library (BGL). The main motivation for the |
---|
302 | property map interface was to support the access of data associated |
---|
303 | with vertices and edges in a graph, though the applicability of |
---|
304 | property maps goes beyond this. |
---|
305 | |
---|
306 | <h3>Acknowledgments</h3> |
---|
307 | |
---|
308 | Thanks go to Dietmar Kühl for coming up with this mechanism, and |
---|
309 | thanks go to the Boost members who helped refine and improve the |
---|
310 | property map interface. Thanks to Dave Abrahams for managing the |
---|
311 | formal review of the BGL which included the property map library. |
---|
312 | |
---|
313 | <h3>Notes to Implementors</h3> |
---|
314 | |
---|
315 | Copying a property map should be inexpensive since they are often |
---|
316 | passed by value. |
---|
317 | |
---|
318 | <br> |
---|
319 | <HR> |
---|
320 | <TABLE> |
---|
321 | <TR valign=top> |
---|
322 | <TD nowrap>Copyright © 2000-2002</TD><TD> |
---|
323 | <a HREF="../../people/jeremy_siek.htm">Jeremy Siek</a>, Indiana University (<A HREF="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</A>) |
---|
324 | </TD></TR></TABLE> |
---|
325 | |
---|
326 | </BODY> |
---|
327 | </HTML> |
---|
328 | <!-- LocalWords: ALT STL html genericity BGL ColorMap htm cpp iostream hpp hl |
---|
329 | --> |
---|
330 | <!-- LocalWords: typename AddressMap foo fred joe joes int writeable lvalue |
---|
331 | --> |
---|
332 | <!-- LocalWords: ReadablePropertyMap WritablePropertyMap ReadWritePropertyMap |
---|
333 | --> |
---|
334 | <!-- LocalWords: LvaluePropertyMap struct namespace PropertyMap pmap const |
---|
335 | --> |
---|
336 | <!-- LocalWords: val Dietmar hl's GGCL Abrahams |
---|
337 | --> |
---|