]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <?xml version="1.0" encoding="utf-8" ?> |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | |
3 | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |
4 | <head> | |
5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
6 | <meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" /> | |
7 | <title>Boost Dynamic Property Maps</title> | |
8 | <link rel="stylesheet" href="../../parameter/doc/html/rst.css" type="text/css" /> | |
9 | </head> | |
10 | <body> | |
11 | <div class="document" id="logo-dynamic-property-maps"> | |
12 | <h1 class="title"><a class="reference external" href="../../../index.htm"><img align="middle" alt="Boost" class="align-middle" src="../../../boost.png" /></a> Dynamic Property Maps</h1> | |
13 | ||
14 | <!-- Copyright 2004-5 The Trustees of Indiana University. | |
15 | ||
16 | Use, modification and distribution is subject to the Boost Software | |
17 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
18 | http://www.boost.org/LICENSE_1_0.txt) --> | |
19 | <div class="section" id="summary"> | |
20 | <h1><a class="toc-backref" href="#id2">Summary</a></h1> | |
21 | <p>The dynamic property map interfaces provides access to a collection of | |
22 | property maps through a dynamically-typed interface. An algorithm can | |
23 | use it to manipulate property maps without knowing their key or | |
24 | value types at compile-time. Type-safe codes can use dynamic property | |
25 | maps to interface more easily and completely with scripting languages | |
26 | and other text-based representations of key-value data.</p> | |
27 | <div class="contents topic" id="contents"> | |
28 | <p class="topic-title first">Contents</p> | |
29 | <ul class="simple"> | |
30 | <li><a class="reference internal" href="#summary" id="id2">Summary</a></li> | |
31 | <li><a class="reference internal" href="#introduction" id="id3">Introduction</a><ul> | |
32 | <li><a class="reference internal" href="#fred-s-info-revisited" id="id4">"Fred's Info" Revisited</a></li> | |
33 | </ul> | |
34 | </li> | |
35 | <li><a class="reference internal" href="#reference" id="id5">Reference</a><ul> | |
36 | <li><a class="reference internal" href="#member-functions" id="id6">Member Functions</a></li> | |
37 | <li><a class="reference internal" href="#free-functions" id="id7">Free functions</a></li> | |
38 | <li><a class="reference internal" href="#exceptions" id="id8">Exceptions</a></li> | |
39 | </ul> | |
40 | </li> | |
41 | </ul> | |
42 | </div> | |
43 | </div> | |
44 | <div class="section" id="introduction"> | |
45 | <h1><a class="toc-backref" href="#id3">Introduction</a></h1> | |
46 | <p>The Boost Property Map library specifies statically type-safe | |
47 | interfaces through which key-value pairs can be manipulated by | |
48 | generic algorithms. Typically, an algorithm that uses property maps is | |
49 | parameterized on the types of the property maps it uses, and it | |
50 | manipulates them using the interfaces specified by the | |
51 | Boost Property Map Library.</p> | |
52 | <p>The following generic function illustrates property map basics.</p> | |
53 | <pre class="literal-block"> | |
54 | template <typename AgeMap, typename GPAMap> | |
55 | void | |
56 | manipulate_freds_info(AgeMap ages, GPAMap gpas) { | |
57 | ||
58 | typedef typename boost::property_traits<AgeMap>::key_type name_type; | |
59 | typedef typename boost::property_traits<AgeMap>::value_type age_type; | |
60 | typedef typename boost::property_traits<GPAMap>::value_type gpa_type; | |
61 | ||
62 | name_type fred = "Fred"; | |
63 | ||
64 | age_type old_age = get(ages, fred); | |
65 | gpa_type old_gpa = get(gpas, fred); | |
66 | ||
67 | std::cout << "Fred's old age: " << old_age << "\n" | |
68 | << "Fred's old gpa: " << old_gpa << "\n"; | |
69 | ||
70 | age_type new_age = 18; | |
71 | gpa_type new_gpa = 3.9; | |
72 | put(ages, fred, new_age); | |
73 | put(gpas, fred, new_gpa); | |
74 | } | |
75 | </pre> | |
76 | <p>The function is parameterized on two property map types, <tt class="docutils literal"><span class="pre">AgeMap</span></tt> and | |
77 | <tt class="docutils literal"><span class="pre">GPAMap</span></tt>, and takes a value parameter for each of those types. The | |
78 | function uses the <tt class="docutils literal"><span class="pre">property_traits</span></tt> interface to ascertain, at | |
79 | compile-time, the value and key types of the property maps. The code | |
80 | then retrieves Fred's old information, using the <tt class="docutils literal"><span class="pre">get</span></tt> function, and | |
81 | updates it using the <tt class="docutils literal"><span class="pre">put</span></tt> function. The <tt class="docutils literal"><span class="pre">get</span></tt> function is required by the | |
82 | Readable Property Map concept and both <tt class="docutils literal"><span class="pre">get</span></tt> and <tt class="docutils literal"><span class="pre">put</span></tt> are required by the | |
83 | Read/Write Property Map concept.</p> | |
84 | <p>The above function not only requires the two type parameters to model | |
85 | property map concepts, but also makes some extra assumptions. | |
86 | <tt class="docutils literal"><span class="pre">AgeMap</span></tt> and <tt class="docutils literal"><span class="pre">GPAMap</span></tt> must have the same key type, and that type must be | |
87 | constructable from a string. Furthermore, <tt class="docutils literal"><span class="pre">AgeMap</span></tt>'s value type must be | |
88 | constructable from an <tt class="docutils literal"><span class="pre">int</span></tt>. Although these requirements are not | |
89 | explicitly stated, they are statically checked during compilation and | |
90 | failure to meet them yields compile-time errors.</p> | |
91 | <p>Although the static typing of property map interfaces usually provides | |
92 | desirable compile-time safety, some algorithms require a more dynamic | |
93 | interface to property maps. For example, the Boost Graph Library (BGL) | |
94 | provides functions that can initialize a graph by interpreting the | |
95 | contents of a textual graph description (i.e. a GraphML file). Such | |
96 | general-purpose graph description languages can specify an arbitrary | |
97 | number of edge and vertex properties, using strings to represent the | |
98 | key-value pairs. A graph reader function should capture these | |
99 | arbitrary properties, but since function templates can only be | |
100 | parameterized on a fixed number of property maps, the traditional | |
101 | techniques for handling property maps do not suffice to implement them.</p> | |
102 | <p>Dynamic property maps specifically address the need for an interface | |
103 | to property maps whose checking is delayed to runtime. Several | |
104 | components combine to provide support for dynamic property maps. The | |
105 | <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> class collects a | |
106 | group of heterogenous objects that model concepts from | |
107 | the Boost Property Map library. Each property map is assigned a | |
108 | string-based key when it is added to the collection, and it can be | |
109 | addressed using that key. Internally, <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> adapts | |
110 | each contained property map with the dynamic property map interface, | |
111 | which provides <tt class="docutils literal"><span class="pre">get</span></tt> and <tt class="docutils literal"><span class="pre">put</span></tt> functions that | |
112 | can be called using values of any type that meets a few requirements. | |
113 | Internally, the dynamic property map converts key and value pairs to | |
114 | meet the requirements of the underlying property map or signals a | |
115 | runtime exception if it cannot.</p> | |
116 | <div class="section" id="fred-s-info-revisited"> | |
117 | <h2><a class="toc-backref" href="#id4">"Fred's Info" Revisited</a></h2> | |
118 | <p>Here's what the example above looks like using the | |
119 | <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> interface:</p> | |
120 | <pre class="literal-block"> | |
121 | void manipulate_freds_info(boost::dynamic_properties& properties) | |
122 | { | |
123 | using boost::get; | |
124 | std::string fred = "Fred"; | |
125 | ||
126 | int old_age = get<int>("age", properties, fred); | |
127 | std::string old_gpa = get("gpa", properties, fred); | |
128 | ||
129 | std::cout << "Fred's old age: " << old_age << "\n" | |
130 | << "Fred's old gpa: " << old_gpa << "\n"; | |
131 | ||
132 | std::string new_age = "18"; | |
133 | double new_gpa = 3.9; | |
134 | put("age",properties,fred,new_age); | |
135 | put("gpa",properties,fred,new_gpa); | |
136 | } | |
137 | </pre> | |
138 | <p>The new function is not a template parameterized on the property map | |
139 | types but instead a concrete function that takes a <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> | |
140 | object. Furthermore, the code no longer makes reference to key or | |
141 | value types: keys and values are represented with strings. | |
142 | Nonetheless the function still uses non-string types where they are | |
143 | useful. For instance, Fred's old age is represented using an <tt class="docutils literal"><span class="pre">int</span></tt>. | |
144 | It's value is retreived by calling <tt class="docutils literal"><span class="pre">get</span></tt> with a | |
145 | type parameter, which determines its return type. Finally, the | |
146 | <tt class="docutils literal"><span class="pre">get</span></tt> and <tt class="docutils literal"><span class="pre">put</span></tt> functions are each supplied a string-based key that | |
147 | differs depending on the property of concern.</p> | |
148 | <p>Here's an example of how the above function might be called.</p> | |
149 | <pre class="literal-block"> | |
150 | int main() | |
151 | { | |
152 | using boost::get; | |
153 | ||
154 | // build property maps using associative_property_map | |
155 | std::map<std::string, int> name2age; | |
156 | std::map<std::string, double> name2gpa; | |
157 | boost::associative_property_map< std::map<std::string, int> > | |
158 | age_map(name2age); | |
159 | boost::associative_property_map< std::map<std::string, double> > | |
160 | gpa_map(name2gpa); | |
161 | ||
162 | std::string fred("Fred"); | |
163 | // add key-value information | |
164 | name2age.insert(make_pair(fred,17)); | |
165 | name2gpa.insert(make_pair(fred,2.7)); | |
166 | ||
167 | // build and populate dynamic interface | |
168 | boost::dynamic_properties properties; | |
169 | properties.property("age",age_map); | |
170 | properties.property("gpa",gpa_map); | |
171 | ||
172 | manipulate_freds_info(properties); | |
173 | ||
174 | std::cout << "Fred's age: " << get(age_map,fred) << "\n" | |
175 | << "Fred's gpa: " << get(gpa_map,fred) << "\n"; | |
176 | } | |
177 | </pre> | |
178 | <p>The code first creates two property maps using <tt class="docutils literal"><span class="pre">std::map</span></tt> and the | |
179 | <tt class="docutils literal"><span class="pre">associative_property_map</span></tt> adaptor. After initializing the | |
180 | property maps with key-value data, it constructs a | |
181 | <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> object and adds to it both property maps, | |
182 | keyed on the strings "age" and "gpa". Finally <tt class="docutils literal"><span class="pre">manipulate_freds_info</span></tt> | |
183 | is passed the <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> object and the results of its changes are | |
184 | displayed.</p> | |
185 | <p>As shown above, the <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> object provides, where needed, a | |
186 | dynamically-typed interface to property maps yet preserves the static | |
187 | typing of property map uses elsewhere in an application.</p> | |
188 | </div> | |
189 | </div> | |
190 | <div class="section" id="reference"> | |
191 | <h1><a class="toc-backref" href="#id5">Reference</a></h1> | |
192 | <pre class="literal-block"> | |
193 | class dynamic_properties | |
194 | </pre> | |
195 | <p>The <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> class provides a dynamically-typed interface to | |
196 | a set of property maps. To use it, one must populate | |
197 | an object of this class with property maps using the <tt class="docutils literal"><span class="pre">property</span></tt> member | |
198 | function.</p> | |
199 | <div class="section" id="member-functions"> | |
200 | <h2><a class="toc-backref" href="#id6">Member Functions</a></h2> | |
201 | <pre class="literal-block"> | |
202 | dynamic_properties() | |
203 | dynamic_properties( | |
204 | const boost::function< | |
205 | boost::shared_ptr<dynamic_property_map> ( | |
206 | const std::string&, const boost::any&, const boost::any&) | |
207 | >& fn) | |
208 | </pre> | |
209 | <p>A <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> object can be constructed with a function object | |
210 | that, when called, creates a new property map. The library provides the | |
211 | <tt class="docutils literal"><span class="pre">ignore_other_properties</span></tt> function object, which lets the <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> object ignore any properties that it hasn't been prepared to record. | |
212 | If an attempt is made | |
213 | to <tt class="docutils literal"><span class="pre">put</span></tt> a key-value pair to a nonexistent <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> key, | |
214 | then this function is called with the <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> key and the | |
215 | intended property key and value . If <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> is | |
216 | default-constructed, such a <tt class="docutils literal"><span class="pre">put</span></tt> attempt throws | |
217 | <tt class="docutils literal"><span class="pre">property_not_found</span></tt>.</p> | |
218 | <pre class="literal-block"> | |
219 | template<typename PropertyMap> | |
220 | dynamic_properties& | |
221 | property(const std::string& name, PropertyMap property_map) | |
222 | </pre> | |
223 | <p>This member function adds a property map to the set of maps contained, | |
224 | using <tt class="docutils literal"><span class="pre">name</span></tt> as its key.</p> | |
225 | <p>Requirements: <tt class="docutils literal"><span class="pre">PropertyMap</span></tt> must model Readable Property Map or | |
226 | Read/Write Property Map.</p> | |
227 | <pre class="literal-block"> | |
228 | void insert(const std::string& name, boost::shared_ptr<dynamic_property_map> pm) | |
229 | </pre> | |
230 | <p>This member function directly adds a <tt class="docutils literal"><span class="pre">dynamic_property_map</span></tt> | |
231 | to the collection, using <tt class="docutils literal"><span class="pre">name</span></tt> as its key.</p> | |
232 | <pre class="literal-block"> | |
233 | iterator begin() | |
234 | const_iterator begin() const | |
235 | </pre> | |
236 | <p>This member function returns an iterator over the set of property maps | |
237 | held by the <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> object.</p> | |
238 | <pre class="literal-block"> | |
239 | iterator end() | |
240 | const_iterator end() const | |
241 | </pre> | |
242 | <p>This member function returns a terminal iterator over the set of | |
243 | dynamic property maps held by the <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> object. It is used to | |
244 | terminate traversals over the set of dynamic property maps</p> | |
245 | <pre class="literal-block"> | |
246 | iterator lower_bound(const std::string& name) | |
247 | </pre> | |
248 | <p>This member function returns an iterator that points to the first | |
249 | property map whose <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> key is <tt class="docutils literal"><span class="pre">name</span></tt>. | |
250 | Bear in mind that multiple property maps may have the same | |
251 | <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> key, so long as their property map key types differ.</p> | |
252 | <p>Invariant: The range [ lower_bound(name), end() ) contains every | |
253 | property map that has name for its <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> key.</p> | |
254 | </div> | |
255 | <div class="section" id="free-functions"> | |
256 | <h2><a class="toc-backref" href="#id7">Free functions</a></h2> | |
257 | <pre class="literal-block"> | |
258 | boost::shared_ptr<boost::dynamic_property_map> | |
259 | ignore_other_properties(const std::string&, | |
260 | const boost::any&, | |
261 | const boost::any&) | |
262 | </pre> | |
263 | <p>When passed to the <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> constructor, this function | |
264 | allows the <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> object to disregard attempts to put | |
265 | values to unknown keys without signaling an error.</p> | |
266 | <pre class="literal-block"> | |
267 | template<typename Key, typename Value> | |
268 | bool put(const std::string& name, dynamic_properties& dp, const Key& key, | |
269 | const Value& value) | |
270 | </pre> | |
271 | <p>This function adds a key-value pair to the property map with the | |
272 | matching name and key type. If no matching property map is found, | |
273 | behavior depends on the availability of a property map generator. If | |
274 | a property map generator was supplied when the <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> | |
275 | object was constructed, then that function is used to create a new | |
276 | property map. If the generator fails to generate a property map | |
277 | (returns a null <tt class="docutils literal"><span class="pre">shared_ptr</span></tt>), then the <tt class="docutils literal"><span class="pre">put</span></tt> function returns | |
278 | <tt class="docutils literal"><span class="pre">false</span></tt>. If, on the other hand, the <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> object | |
279 | has no property map generator (meaning it was default-constructed), | |
280 | then <tt class="docutils literal"><span class="pre">property_not_found</span></tt> is thrown. If a candidate property map is | |
281 | found but it does not support <tt class="docutils literal"><span class="pre">put</span></tt>, <tt class="docutils literal"><span class="pre">dynamic_const_put_error</span></tt> is | |
282 | thrown.</p> | |
283 | <pre class="literal-block"> | |
284 | template<typename Value, typename Key> | |
285 | Value get(const std::string& name, const dynamic_properties& dp, | |
286 | const Key& key) | |
287 | </pre> | |
288 | <p>This function gets the value from the property-map whose namee is | |
289 | given and whose key type matches. If <tt class="docutils literal"><span class="pre">Value</span></tt> is <tt class="docutils literal"><span class="pre">std::string</span></tt>, then the | |
290 | property map's value type must either be <tt class="docutils literal"><span class="pre">std::string</span></tt> or model | |
291 | OutputStreamable. In the latter case, the <tt class="docutils literal"><span class="pre">get</span></tt> function converts the | |
292 | value to a string. If no matching property map is found, | |
293 | <tt class="docutils literal"><span class="pre">dynamic_get_failure</span></tt> is thrown.</p> | |
294 | <hr class="docutils" /> | |
295 | <pre class="literal-block"> | |
296 | class dynamic_property_map | |
297 | </pre> | |
298 | <p>This class describes the interface used by <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> to | |
299 | interact with a user's property maps polymorphically.</p> | |
300 | <pre class="literal-block"> | |
301 | boost::any get(const any& key) | |
302 | </pre> | |
303 | <p>Given a representation of a key, return the value associated with that key.</p> | |
304 | <p>Requirement: | |
305 | 1) The object passed as the key must be convertible to a value of the | |
306 | map's key type. Details of that conversion are unspecified. | |
307 | 2) For this expression to be valid, the key must be | |
308 | associated with some value, otherwise the result is undefined.</p> | |
309 | <pre class="literal-block"> | |
310 | std::string get_string(const any& key) | |
311 | </pre> | |
312 | <p>Given a representation of a key, return the string representation | |
313 | of the value associated with that key.</p> | |
314 | <p>Requirements: | |
315 | 1) The object passed as the key must be convertible to the | |
316 | property map's key type. Details of that conversion are unspecified. | |
317 | 2) For this expression to be valid, the key must be | |
318 | associated with some value, otherwise the result is undefined. | |
319 | 3) The value type of the property map must model Output Streamable.</p> | |
320 | <pre class="literal-block"> | |
321 | void put(const any& key, const any& value) | |
322 | </pre> | |
323 | <p>Given a representation of a key and a representation of a value, the | |
324 | key and value are associated in the property map.</p> | |
325 | <p>Requirements: | |
326 | 1) The object passed as the key must be convertible to the | |
327 | property map's key type. Details of that conversion are unspecified. | |
328 | 2) The object passed as the value must be convertible to the | |
329 | property map's value type. Details of that conversion are unspecified. | |
330 | 3) The property map need not support this member function, in which | |
331 | case an error will be signaled. This is the runtime analogue of the | |
332 | Readable Property Map concept.</p> | |
333 | <pre class="literal-block"> | |
334 | const std::type_info& key() const | |
335 | </pre> | |
336 | <p>Returns a <tt class="docutils literal"><span class="pre">type_info</span></tt> object that represents the property map's key type.</p> | |
337 | <pre class="literal-block"> | |
338 | const std::type_info& value() const | |
339 | </pre> | |
340 | <p>Returns a <tt class="docutils literal"><span class="pre">type_info</span></tt> object that represents the property map's value type.</p> | |
341 | </div> | |
342 | <div class="section" id="exceptions"> | |
343 | <h2><a class="toc-backref" href="#id8">Exceptions</a></h2> | |
344 | <pre class="literal-block"> | |
345 | struct dynamic_property_exception : public std::exception { | |
346 | virtual ~dynamic_property_exception() throw() {} | |
347 | }; | |
348 | ||
349 | struct property_not_found : public std::exception { | |
350 | std::string property; | |
351 | property_not_found(const std::string& property); | |
352 | virtual ~property_not_found() throw(); | |
353 | ||
354 | const char* what() const throw(); | |
355 | }; | |
356 | ||
357 | struct dynamic_get_failure : public std::exception { | |
358 | std::string property; | |
359 | dynamic_get_failure(const std::string& property); | |
360 | virtual ~dynamic_get_failure() throw(); | |
361 | ||
362 | const char* what() const throw(); | |
363 | }; | |
364 | ||
365 | struct dynamic_const_put_error : public std::exception { | |
366 | virtual ~dynamic_const_put_error() throw(); | |
367 | ||
368 | const char* what() const throw(); | |
369 | }; | |
370 | </pre> | |
371 | <p>Under certain circumstances, calls to <tt class="docutils literal"><span class="pre">dynamic_properties</span></tt> member | |
372 | functions will throw one of the above exceptions. The three concrete | |
373 | exceptions can all be caught using the general | |
374 | <tt class="docutils literal"><span class="pre">dynamic_property_exception</span></tt> moniker when greater precision is not | |
375 | needed. In addition, all of the above exceptions derive from the | |
376 | standard <tt class="docutils literal"><span class="pre">std::exception</span></tt> for even more generalized error handling. | |
377 | The specific circumstances that result in these exceptions are | |
378 | described above.</p> | |
379 | </div> | |
380 | </div> | |
381 | </div> | |
382 | <div class="footer"> | |
383 | <hr class="footer" /> | |
384 | Generated on: 2010-03-29 18:04 UTC. | |
385 | Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source. | |
386 | ||
387 | </div> | |
388 | </body> | |
389 | </html> |