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