]>
Commit | Line | Data |
---|---|---|
1 | <?xml version="1.0" encoding="utf-8"?> | |
2 | <!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" | |
3 | "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> | |
4 | <library name="Any" dirname="any" xmlns:xi="http://www.w3.org/2001/XInclude" | |
5 | id="any" last-revision="$Date$"> | |
6 | <libraryinfo> | |
7 | <author> | |
8 | <firstname>Kevlin</firstname> | |
9 | <surname>Henney</surname> | |
10 | </author> | |
11 | ||
12 | <copyright> | |
13 | <year>2001</year> | |
14 | <holder>Kevlin Henney</holder> | |
15 | </copyright> | |
16 | ||
17 | <librarypurpose> | |
18 | Safe, generic container for single values of different value types | |
19 | </librarypurpose> | |
20 | <librarycategory name="category:data-structures"/> | |
21 | ||
22 | <legalnotice> | |
23 | <para>Distributed under the Boost Software License, Version 1.0. | |
24 | (See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at | |
25 | <ulink | |
26 | url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>) | |
27 | </para> | |
28 | </legalnotice> | |
29 | </libraryinfo> | |
30 | ||
31 | <title>Boost.Any</title> | |
32 | ||
33 | <section> | |
34 | <title>Introduction</title> | |
35 | ||
36 | <para>There are times when a generic (in the sense of | |
37 | <emphasis>general</emphasis> as opposed to | |
38 | <emphasis>template-based programming</emphasis>) type is needed: | |
39 | variables that are truly variable, accommodating values of many | |
40 | other more specific types rather than C++'s normal strict and | |
41 | static types. We can distinguish three basic kinds of generic | |
42 | type:</para> | |
43 | ||
44 | <itemizedlist> | |
45 | <listitem> | |
46 | <para>Converting types that can hold one of a number of | |
47 | possible value types, e.g. <code>int</code> and | |
48 | <code>string</code>, and freely convert between them, for | |
49 | instance interpreting <code>5</code> as <code>"5"</code> or | |
50 | vice-versa. Such types are common in scripting and other | |
51 | interpreted | |
52 | languages. | |
53 | <code><functionname>boost::lexical_cast</functionname></code> | |
54 | supports such conversion functionality.</para> | |
55 | </listitem> | |
56 | <listitem> | |
57 | <para> | |
58 | Discriminated types that contain values of different types but | |
59 | do not attempt conversion between them, i.e. <code>5</code> is | |
60 | held strictly as an <code>int</code> and is not implicitly | |
61 | convertible either to <code>"5"</code> or to | |
62 | <code>5.0</code>. Their indifference to interpretation but | |
63 | awareness of type effectively makes them safe, generic | |
64 | containers of single values, with no scope for surprises from | |
65 | ambiguous conversions.</para> | |
66 | </listitem> | |
67 | <listitem> | |
68 | <para> | |
69 | Indiscriminate types that can refer to anything but are | |
70 | oblivious to the actual underlying type, entrusting all forms | |
71 | of access and interpretation to the programmer. This niche is | |
72 | dominated by <code>void *</code>, which offers plenty of scope | |
73 | for surprising, undefined behavior.</para> | |
74 | </listitem> | |
75 | </itemizedlist> | |
76 | ||
77 | <para>The <code><classname>boost::any</classname></code> class | |
78 | (based on the class of the same name described in <ulink | |
79 | url="http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf">"Valued | |
80 | Conversions"</ulink> by Kevlin Henney, <emphasis>C++ | |
81 | Report</emphasis> 12(7), July/August 2000) is a variant value type | |
82 | based on the second category. It supports copying of any value | |
83 | type and safe checked extraction of that value strictly against | |
84 | its type. A similar design, offering more appropriate operators, | |
85 | can be used for a generalized function adaptor, | |
86 | <code>any_function</code>, a generalized iterator adaptor, | |
87 | <code>any_iterator</code>, and other object types that need | |
88 | uniform runtime treatment but support only compile-time template | |
89 | parameter conformance.</para> | |
90 | </section> | |
91 | ||
92 | <section> | |
93 | <title>Examples</title> | |
94 | ||
95 | <using-namespace name="boost"/> | |
96 | <using-class name="boost::any"/> | |
97 | ||
98 | <para>The following code demonstrates the syntax for using | |
99 | implicit conversions to and copying of any objects:</para> | |
100 | ||
101 | <programlisting name="any.example.first"> | |
102 | #include <list> | |
103 | #include <boost/any.hpp> | |
104 | ||
105 | using <functionname>boost::any_cast</functionname>; | |
106 | typedef std::list<<classname>boost::any</classname>> many; | |
107 | ||
108 | void append_int(many & values, int value) | |
109 | { | |
110 | <classname>boost::any</classname> to_append = value; | |
111 | values.push_back(to_append); | |
112 | } | |
113 | ||
114 | void append_string(many & values, const std::string & value) | |
115 | { | |
116 | values.push_back(value); | |
117 | } | |
118 | ||
119 | void append_char_ptr(many & values, const char * value) | |
120 | { | |
121 | values.push_back(value); | |
122 | } | |
123 | ||
124 | void append_any(many & values, const <classname>boost::any</classname> & value) | |
125 | { | |
126 | values.push_back(value); | |
127 | } | |
128 | ||
129 | void append_nothing(many & values) | |
130 | { | |
131 | values.push_back(<classname>boost::any</classname>()); | |
132 | } | |
133 | </programlisting> | |
134 | ||
135 | <para>The following predicates follow on from the previous | |
136 | definitions and demonstrate the use of queries on any | |
137 | objects:</para> | |
138 | ||
139 | <programlisting name="any.example.second"> | |
140 | bool is_empty(const <classname>boost::any</classname> & operand) | |
141 | { | |
142 | return operand.<methodname>empty</methodname>(); | |
143 | } | |
144 | ||
145 | bool is_int(const <classname>boost::any</classname> & operand) | |
146 | { | |
147 | return operand.<methodname>type</methodname>() == typeid(int); | |
148 | } | |
149 | ||
150 | bool is_char_ptr(const <classname>boost::any</classname> & operand) | |
151 | { | |
152 | try | |
153 | { | |
154 | <functionname>any_cast</functionname><const char *>(operand); | |
155 | return true; | |
156 | } | |
157 | catch(const <classname>boost::bad_any_cast</classname> &) | |
158 | { | |
159 | return false; | |
160 | } | |
161 | } | |
162 | ||
163 | bool is_string(const <classname>boost::any</classname> & operand) | |
164 | { | |
165 | return <functionname>any_cast</functionname><std::string>(&operand); | |
166 | } | |
167 | ||
168 | void count_all(many & values, std::ostream & out) | |
169 | { | |
170 | out << "#empty == " | |
171 | << std::count_if(values.begin(), values.end(), is_empty) << std::endl; | |
172 | out << "#int == " | |
173 | << std::count_if(values.begin(), values.end(), is_int) << std::endl; | |
174 | out << "#const char * == " | |
175 | << std::count_if(values.begin(), values.end(), is_char_ptr) << std::endl; | |
176 | out << "#string == " | |
177 | << std::count_if(values.begin(), values.end(), is_string) << std::endl; | |
178 | } | |
179 | </programlisting> | |
180 | ||
181 | <para>The following type, patterned after the OMG's Property Service, defines name-value pairs for arbitrary value types:</para> | |
182 | ||
183 | <programlisting> | |
184 | struct property | |
185 | { | |
186 | property(); | |
187 | property(const std::string &, const <classname>boost::any</classname> &); | |
188 | ||
189 | std::string name; | |
190 | <classname>boost::any</classname> value; | |
191 | }; | |
192 | ||
193 | typedef std::list<property> properties; | |
194 | </programlisting> | |
195 | ||
196 | <para>The following base class demonstrates one approach to | |
197 | runtime polymorphism based callbacks that also require arbitrary | |
198 | argument types. The absence of virtual member templates requires | |
199 | that different solutions have different trade-offs in terms of | |
200 | efficiency, safety, and generality. Using a checked variant type | |
201 | offers one approach:</para> | |
202 | ||
203 | <programlisting> | |
204 | class consumer | |
205 | { | |
206 | public: | |
207 | virtual void notify(const <classname>any</classname> &) = 0; | |
208 | ... | |
209 | }; | |
210 | </programlisting> | |
211 | </section> | |
212 | ||
213 | <library-reference> | |
214 | <section id="any.ValueType"> | |
215 | <title><emphasis>ValueType</emphasis> requirements</title> | |
216 | ||
217 | <para>Values are strongly informational objects for which | |
218 | identity is not significant, i.e. the focus is principally on | |
219 | their state content and any behavior organized around | |
220 | that. Another distinguishing feature of values is their | |
221 | granularity: normally fine-grained objects representing simple | |
222 | concepts in the system such as quantities.</para> | |
223 | ||
224 | <para>As the emphasis of a value lies in its state not its | |
225 | identity, values can be copied and typically assigned one to | |
226 | another, requiring the explicit or implicit definition of a | |
227 | public copy constructor and public assignment operator. Values | |
228 | typically live within other scopes, i.e. within objects or | |
229 | blocks, rather than on the heap. Values are therefore normally | |
230 | passed around and manipulated directly as variables or through | |
231 | references, but not as pointers that emphasize identity and | |
232 | indirection.</para> | |
233 | ||
234 | <para>The specific requirements on value types to be used in an | |
235 | <code><classname alt="boost::any">any</classname></code> | |
236 | are:</para> | |
237 | ||
238 | <itemizedlist spacing="compact"> | |
239 | <listitem><simpara>A <emphasis>ValueType</emphasis> is | |
240 | <emphasis>CopyConstructible</emphasis> [20.1.3].</simpara> | |
241 | </listitem> | |
242 | ||
243 | <listitem><simpara>The destructor for a | |
244 | <emphasis>ValueType</emphasis> upholds the no-throw | |
245 | exception-safety guarantee.</simpara> | |
246 | </listitem> | |
247 | </itemizedlist> | |
248 | </section> | |
249 | ||
250 | <header name="boost/any.hpp"> | |
251 | <namespace name="boost"> | |
252 | <class name="bad_any_cast"> | |
253 | <inherit access="public"> | |
254 | <classname>std::bad_cast</classname> | |
255 | </inherit> | |
256 | <purpose>The exception thrown in the event of a failed | |
257 | <code><functionname>any_cast</functionname></code> of an | |
258 | <code><classname>any</classname></code> value.</purpose> | |
259 | ||
260 | <method name="what" specifiers="virtual" cv="const"> | |
261 | <type>const char *</type> | |
262 | </method> | |
263 | </class> | |
264 | ||
265 | <class name="any"> | |
266 | <purpose>A class whose instances can hold instances of any | |
267 | type that satisfies <link | |
268 | linkend="any.ValueType">ValueType</link> | |
269 | requirements.</purpose> | |
270 | ||
271 | <constructor> | |
272 | <postconditions><simpara><code>this-><methodname>empty</methodname>()</code></simpara></postconditions> | |
273 | </constructor> | |
274 | ||
275 | <constructor> | |
276 | <parameter name="other"> | |
277 | <paramtype>const <classname>any</classname> &</paramtype> | |
278 | </parameter> | |
279 | ||
280 | <effects><simpara> Copy constructor that copies content of | |
281 | <code>other</code> into new instance, so that any content | |
282 | is equivalent in both type and value to the content of | |
283 | <code>other</code>, or empty if <code>other</code> is | |
284 | empty. </simpara></effects> | |
285 | ||
286 | <throws><simpara>May fail with a | |
287 | <code><classname>std::bad_alloc</classname></code> | |
288 | exception or any exceptions arising from the copy | |
289 | constructor of the contained type.</simpara></throws> | |
290 | </constructor> | |
291 | ||
292 | <constructor> | |
293 | <parameter name="other"> | |
294 | <paramtype><classname>any</classname> &&</paramtype> | |
295 | </parameter> | |
296 | ||
297 | <effects><simpara> Move constructor that moves content of | |
298 | <code>other</code> into new instance and leaves <code>other</code> | |
299 | empty. </simpara></effects> | |
300 | <precondition>C++11 compatible compiler.</precondition> | |
301 | <postconditions><simpara><code>other-><methodname>empty</methodname>()</code></simpara></postconditions> | |
302 | <throws><simpara>Nothing.</simpara></throws> | |
303 | </constructor> | |
304 | ||
305 | <constructor> | |
306 | <template> | |
307 | <template-type-parameter name="ValueType"/> | |
308 | </template> | |
309 | ||
310 | <parameter name="value"> | |
311 | <paramtype>const ValueType &</paramtype> | |
312 | </parameter> | |
313 | ||
314 | <effects><simpara>Makes a copy of <code>value</code>, so | |
315 | that the initial content of the new instance is equivalent | |
316 | in both type and value to | |
317 | <code>value</code>.</simpara></effects> | |
318 | ||
319 | <throws><simpara><code><classname>std::bad_alloc</classname></code> | |
320 | or any exceptions arising from the copy constructor of the | |
321 | contained type.</simpara></throws> | |
322 | </constructor> | |
323 | ||
324 | <constructor> | |
325 | <template> | |
326 | <template-type-parameter name="ValueType"/> | |
327 | </template> | |
328 | ||
329 | <parameter name="value"> | |
330 | <paramtype>ValueType &&</paramtype> | |
331 | </parameter> | |
332 | ||
333 | <effects><simpara>Forwards <code>value</code>, so | |
334 | that the initial content of the new instance is equivalent | |
335 | in both type and value to | |
336 | <code>value</code> before the forward.</simpara></effects> | |
337 | ||
338 | <precondition>C++11 compatible compiler.</precondition> | |
339 | <throws><simpara><code><classname>std::bad_alloc</classname></code> | |
340 | or any exceptions arising from the copy constructor of the | |
341 | contained type.</simpara></throws> | |
342 | </constructor> | |
343 | ||
344 | <destructor> | |
345 | <effects><simpara>Releases any and all resources used in | |
346 | management of instance.</simpara></effects> | |
347 | <throws><simpara>Nothing.</simpara></throws> | |
348 | </destructor> | |
349 | ||
350 | <copy-assignment> | |
351 | <type><classname>any</classname> &</type> | |
352 | ||
353 | <parameter name="rhs"> | |
354 | <paramtype>const <classname>any</classname> &</paramtype> | |
355 | </parameter> | |
356 | ||
357 | <effects><simpara>Copies content of <code>rhs</code> into | |
358 | current instance, discarding previous content, so that the | |
359 | new content is equivalent in both type and value to the | |
360 | content of <code>rhs</code>, or empty if | |
361 | <code>rhs.<methodname>empty</methodname>()</code>.</simpara></effects> | |
362 | ||
363 | <throws><simpara><code><classname>std::bad_alloc</classname></code> | |
364 | or any exceptions arising from the copy constructor of the | |
365 | contained type. Assignment satisfies the strong guarantee | |
366 | of exception safety.</simpara></throws> | |
367 | </copy-assignment> | |
368 | ||
369 | <copy-assignment> | |
370 | <type><classname>any</classname> &</type> | |
371 | ||
372 | <parameter name="rhs"> | |
373 | <paramtype><classname>any</classname> &&</paramtype> | |
374 | </parameter> | |
375 | ||
376 | <effects><simpara>Moves content of <code>rhs</code> into | |
377 | current instance, discarding previous content, so that the | |
378 | new content is equivalent in both type and value to the | |
379 | content of <code>rhs</code> before move, or empty if | |
380 | <code>rhs.<methodname>empty</methodname>()</code>.</simpara></effects> | |
381 | ||
382 | <precondition>C++11 compatible compiler.</precondition> | |
383 | <postconditions><simpara><code>rhs-><methodname>empty</methodname>()</code></simpara></postconditions> | |
384 | <throws><simpara>Nothing.</simpara></throws> | |
385 | </copy-assignment> | |
386 | ||
387 | <copy-assignment> | |
388 | <template> | |
389 | <template-type-parameter name="ValueType"/> | |
390 | </template> | |
391 | ||
392 | <type><classname>any</classname> &</type> | |
393 | ||
394 | <parameter name="rhs"> | |
395 | <paramtype>const ValueType &</paramtype> | |
396 | </parameter> | |
397 | ||
398 | <effects><simpara>Makes a copy of <code>rhs</code>, | |
399 | discarding previous content, so that the new content of is | |
400 | equivalent in both type and value to | |
401 | <code>rhs</code>.</simpara></effects> | |
402 | ||
403 | <throws><simpara><code><classname>std::bad_alloc</classname></code> | |
404 | or any exceptions arising from the copy constructor of the | |
405 | contained type. Assignment satisfies the strong guarantee | |
406 | of exception safety.</simpara></throws> | |
407 | </copy-assignment> | |
408 | ||
409 | <copy-assignment> | |
410 | <template> | |
411 | <template-type-parameter name="ValueType"/> | |
412 | </template> | |
413 | ||
414 | <type><classname>any</classname> &</type> | |
415 | ||
416 | <parameter name="rhs"> | |
417 | <paramtype>ValueType &&</paramtype> | |
418 | </parameter> | |
419 | ||
420 | <effects><simpara>Forwards <code>rhs</code>, | |
421 | discarding previous content, so that the new content of is | |
422 | equivalent in both type and value to | |
423 | <code>rhs</code> before forward.</simpara></effects> | |
424 | ||
425 | <precondition>C++11 compatible compiler.</precondition> | |
426 | <throws><simpara><code><classname>std::bad_alloc</classname></code> | |
427 | or any exceptions arising from the move or copy constructor of the | |
428 | contained type. Assignment satisfies the strong guarantee | |
429 | of exception safety.</simpara></throws> | |
430 | </copy-assignment> | |
431 | ||
432 | <method-group name="modifiers"> | |
433 | <method name="swap"> | |
434 | <type><classname>any</classname> &</type> | |
435 | ||
436 | <parameter name="rhs"> | |
437 | <paramtype><classname>any</classname> &</paramtype> | |
438 | </parameter> | |
439 | ||
440 | <effects><simpara>Exchange of the contents of | |
441 | <code>*this</code> and | |
442 | <code>rhs</code>.</simpara></effects> | |
443 | ||
444 | <returns><simpara><code>*this</code></simpara></returns> | |
445 | ||
446 | <throws><simpara>Nothing.</simpara></throws> | |
447 | </method> | |
448 | </method-group> | |
449 | ||
450 | <method-group name="queries"> | |
451 | <method name="empty" cv="const"> | |
452 | <type>bool</type> | |
453 | ||
454 | <returns><simpara><code>true</code> if instance is | |
455 | empty, otherwise <code>false</code>.</simpara></returns> | |
456 | ||
457 | <throws><simpara>Nothing.</simpara></throws> | |
458 | </method> | |
459 | ||
460 | <method name="type" cv="const"> | |
461 | <type>const <classname>std::type_info</classname> &</type> | |
462 | ||
463 | <returns><simpara>the <code>typeid</code> of the | |
464 | contained value if instance is non-empty, otherwise | |
465 | <code>typeid(void)</code>.</simpara></returns> | |
466 | ||
467 | <notes><simpara>Useful for querying against types known | |
468 | either at compile time or only at | |
469 | runtime.</simpara></notes> | |
470 | </method> | |
471 | </method-group> | |
472 | </class> | |
473 | ||
474 | <function name="swap"> | |
475 | <type>void</type> | |
476 | <parameter name="lhs"> | |
477 | <paramtype><classname>any</classname> &</paramtype> | |
478 | </parameter> | |
479 | <parameter name="rhs"> | |
480 | <paramtype><classname>any</classname> &</paramtype> | |
481 | </parameter> | |
482 | ||
483 | <effects><simpara>Exchange of the contents of | |
484 | <code>lhs</code> and | |
485 | <code>rhs</code>.</simpara></effects> | |
486 | ||
487 | <throws><simpara>Nothing.</simpara></throws> | |
488 | </function> | |
489 | ||
490 | <overloaded-function name="any_cast"> | |
491 | <signature> | |
492 | <template> | |
493 | <template-type-parameter name="T"/> | |
494 | </template> | |
495 | ||
496 | <type>T</type> | |
497 | ||
498 | <parameter name="operand"> | |
499 | <paramtype><classname>any</classname> &</paramtype> | |
500 | </parameter> | |
501 | </signature> | |
502 | ||
503 | <signature> | |
504 | <template> | |
505 | <template-type-parameter name="T"/> | |
506 | </template> | |
507 | ||
508 | <type>T</type> | |
509 | ||
510 | <parameter name="operand"> | |
511 | <paramtype><classname>any</classname> &&</paramtype> | |
512 | </parameter> | |
513 | </signature> | |
514 | ||
515 | <signature> | |
516 | <template> | |
517 | <template-type-parameter name="T"/> | |
518 | </template> | |
519 | ||
520 | <type>T</type> | |
521 | ||
522 | <parameter name="operand"> | |
523 | <paramtype>const <classname>any</classname> &</paramtype> | |
524 | </parameter> | |
525 | </signature> | |
526 | ||
527 | <signature> | |
528 | <template> | |
529 | <template-type-parameter name="ValueType"/> | |
530 | </template> | |
531 | ||
532 | <type>const ValueType *</type> | |
533 | ||
534 | <parameter name="operand"> | |
535 | <paramtype>const <classname>any</classname> *</paramtype> | |
536 | </parameter> | |
537 | </signature> | |
538 | ||
539 | <signature> | |
540 | <template> | |
541 | <template-type-parameter name="ValueType"/> | |
542 | </template> | |
543 | ||
544 | <type>ValueType *</type> | |
545 | ||
546 | <parameter name="operand"> | |
547 | <paramtype><classname>any</classname> *</paramtype> | |
548 | </parameter> | |
549 | </signature> | |
550 | ||
551 | <purpose><simpara>Custom keyword cast for extracting a value | |
552 | of a given type from an | |
553 | <code><classname>any</classname></code>.</simpara></purpose> | |
554 | ||
555 | <returns><simpara> If passed a pointer, it returns a | |
556 | similarly qualified pointer to the value content if | |
557 | successful, otherwise null is returned. | |
558 | If T is ValueType, it returns a copy of the held value, otherwise, if T is a reference | |
559 | to (possibly const qualified) ValueType, it returns a reference to the held | |
560 | value.</simpara></returns> | |
561 | ||
562 | <throws><simpara>Overloads taking an | |
563 | <code><classname>any</classname></code> pointer do not | |
564 | throw; overloads taking an | |
565 | <code><classname>any</classname></code> value or reference | |
566 | throws <code><classname>bad_any_cast</classname></code> if | |
567 | unsuccessful.</simpara></throws> | |
568 | ||
569 | </overloaded-function> | |
570 | </namespace> | |
571 | </header> | |
572 | </library-reference> | |
573 | ||
574 | <section> | |
575 | <title>Acknowledgements</title> | |
576 | ||
577 | <para>Doug Gregor ported the documentation to the BoostBook format.</para> | |
578 | </section> | |
579 | </library> |