dynamic_property_map.rst 15 KB

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