]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/type_erasure/doc/type_erasure.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / type_erasure / doc / type_erasure.qbk
CommitLineData
7c673cae
FG
1[library Boost.TypeErasure
2 [quickbook 1.5]
3 [authors [Watanabe, Steven]]
4 [copyright 2011-2013 Steven Watanabe]
5 [license
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE_1_0.txt or copy at
8 [@http://www.boost.org/LICENSE_1_0.txt])
9 ]
10 [purpose Runtime polymorphism based on concepts]
11]
12
13[def __any [classref boost::type_erasure::any any]]
14[def __any_cast [funcref boost::type_erasure::any_cast any_cast]]
15[def __tuple [classref boost::type_erasure::tuple tuple]]
16[def __rebind_any [classref boost::type_erasure::rebind_any rebind_any]]
17[def __derived [classref boost::type_erasure::derived derived]]
18[def __concept_interface [classref boost::type_erasure::concept_interface concept_interface]]
19[def __constructible [classref boost::type_erasure::constructible constructible]]
20[def __destructible [classref boost::type_erasure::destructible destructible]]
21[def __copy_constructible [classref boost::type_erasure::copy_constructible copy_constructible]]
22[def __assignable [classref boost::type_erasure::assignable assignable]]
23[def __typeid_ [classref boost::type_erasure::typeid_ typeid_]]
24[def __relaxed [classref boost::type_erasure::relaxed relaxed]]
25[def __binding [classref boost::type_erasure::binding binding]]
26[def __static_binding [classref boost::type_erasure::static_binding static_binding]]
27[def __placeholder [classref boost::type_erasure::placeholder placeholder]]
28[def __call [funcref boost::type_erasure::call call]]
29[def __deduced [classref boost::type_erasure::deduced deduced]]
30[def __as_param [classref boost::type_erasure::as_param as_param]]
31
32[def __addable [classref boost::type_erasure::addable addable]]
33[def __subtractable [classref boost::type_erasure::subtractable subtractable]]
34[def __multipliable [classref boost::type_erasure::multipliable multipliable]]
35[def __dividable [classref boost::type_erasure::dividable dividable]]
36[def __modable [classref boost::type_erasure::modable modable]]
37[def __bitandable [classref boost::type_erasure::bitandable bitandable]]
38[def __bitorable [classref boost::type_erasure::bitorable bitorable]]
39[def __bitxorable [classref boost::type_erasure::bitxorable bitxorable]]
40[def __left_shiftable [classref boost::type_erasure::left_shiftable left_shiftable]]
41[def __right_shiftable [classref boost::type_erasure::right_shiftable right_shiftable]]
42[def __add_assignable [classref boost::type_erasure::add_assignable add_assignable]]
43[def __subtract_assignable [classref boost::type_erasure::subtract_assignable subtract_assignable]]
44[def __multiply_assignable [classref boost::type_erasure::multiply_assignable multiply_assignable]]
45[def __divide_assignable [classref boost::type_erasure::divide_assignable divide_assignable]]
46[def __mod_assignable [classref boost::type_erasure::mod_assignable mod_assignable]]
47[def __bitand_assignable [classref boost::type_erasure::bitand_assignable bitand_assignable]]
48[def __bitor_assignable [classref boost::type_erasure::bitor_assignable bitor_assignable]]
49[def __bitxor_assignable [classref boost::type_erasure::bitxor_assignable bitxor_assignable]]
50[def __left_shift_assignable [classref boost::type_erasure::left_shift_assignable left_shift_assignable]]
51[def __right_shift_assignable [classref boost::type_erasure::right_shift_assignable right_shift_assignable]]
52[def __incrementable [classref boost::type_erasure::incrementable incrementable]]
53[def __decrementable [classref boost::type_erasure::decrementable decrementable]]
54[def __negatable [classref boost::type_erasure::negatable negatable]]
55[def __complementable [classref boost::type_erasure::complementable complementable]]
56[def __dereferenceable [classref boost::type_erasure::dereferenceable dereferenceable]]
57[def __callable [classref boost::type_erasure::callable callable]]
58[def __subscriptable [classref boost::type_erasure::subscriptable subscriptable]]
59[def __equality_comparable [classref boost::type_erasure::equality_comparable equality_comparable]]
60[def __less_than_comparable [classref boost::type_erasure::less_than_comparable less_than_comparable]]
61[def __ostreamable [classref boost::type_erasure::ostreamable ostreamable]]
62[def __istreamable [classref boost::type_erasure::istreamable istreamable]]
63[def __iterator [classref boost::type_erasure::iterator iterator]]
64[def __forward_iterator [classref boost::type_erasure::forward_iterator forward_iterator]]
65[def __bidirectional_iterator [classref boost::type_erasure::bidirectional_iterator bidirectional_iterator]]
66[def __random_access_iterator [classref boost::type_erasure::random_access_iterator random_access_iterator]]
67[def __same_type [classref boost::type_erasure::same_type same_type]]
68
69[def __BOOST_TYPE_ERASURE_MEMBER [macroref BOOST_TYPE_ERASURE_MEMBER]]
70[def __BOOST_TYPE_ERASURE_FREE [macroref BOOST_TYPE_ERASURE_FREE]]
71
72[section:introduction Introduction]
73
74The Boost.TypeErasure library provides runtime polymorphism
75in C++ that is more flexible than that provided by the
76core language.
77
78C++ has two distinct kinds of polymorphism,
79virtual functions and templates, each of which has
80its own advantages and disadvantages.
81
82* Virtual functions are not resolved until runtime,
83 while templates are always resolved at compile
84 time. If your types can vary at runtime (for
85 example, if they depend on user input), then
86 static polymorphism with templates doesn't help much.
87* Virtual functions can be used with separate compilation.
88 The body of a template has to be available
89 in every translation unit in which it is used,
90 slowing down compiles and increasing rebuilds.
91* Virtual functions automatically make the requirements
92 on the arguments explicit. Templates are only
93 checked when they're instantiated, requiring
94 extra work in testing, assertions, and documentation.
95* The compiler creates a new copy of each function
96 template every time it is instantiated. This
97 allows better optimization, because the compiler
98 knows everything statically, but it also causes
99 a significant increase of binary sizes.
100* Templates support Value semantics. Objects that
101 "behave like an int" and are not shared are easier
102 to reason about. To use virtual functions, on
103 the other hand, you have to use (smart) pointers
104 or references.
105* Template libraries can allow third-party types to
106 be adapted non-intrusively for seamless interoperability.
107 With virtual functions, you have to create a wrapper
108 that inherits from the base class.
109* Templates can handle constraints involving
110 multiple types. For example, std::for_each
111 takes an iterator range and a function that
112 can be called on the elements of the range.
113 Virtual functions aren't really able to
114 express such constraints.
115
116The Boost.TypeErasure library combines the superior
117abstraction capabilities of templates, with the
118runtime flexibility of virtual functions.
119
120Boost includes several special cases of this kind
121of polymorphism:
122
123* `boost::any` for CopyConstructible types.
124* `boost::function` for objects that can be called like functions.
125* Boost.Range provides `any_iterator`.
126
127Boost.TypeErasure generalizes this to support arbitrary
128requirements and provides a
129[link boost_typeerasure.predef predefined set of common concepts]
130
131[endsect]
132
133[section:reading How to read this documentation]
134
135To avoid excessive verbosity, all the examples
136assume that a few using directives are in place.
137
138 namespace mpl = boost::mpl;
139 using namespace boost::type_erasure;
140
141[endsect]
142
143[section:basic Basic Usage]
144[import ../example/basic.cpp]
145[basic]
146[endsect]
147
148[section Composing Concepts]
149[import ../example/compose.cpp]
150[compose]
151[endsect]
152
153[section:multi Functions with Multiple Arguments]
154[import ../example/multi.cpp]
155[multi]
156[endsect]
157
158[section:concept Concepts in Depth]
159
160[section:custom Defining Custom Concepts]
161[import ../example/custom.cpp]
162[custom]
163[endsect]
164
165[section:overload Overloading]
166[import ../example/overload.cpp]
167[overload]
168[endsect]
169
170[section:concept_map Concept Maps]
171[import ../example/concept_map.cpp]
172[concept_map]
173[endsect]
174
175[section:overload Associated Types]
176[import ../example/associated.cpp]
177[associated]
178[endsect]
179
180[endsect]
181
182[section:any Using Any]
183
184[section:construction Construction]
185[import ../example/construction.cpp]
186[construction]
187[endsect]
188
189[section Conversions]
190[import ../example/convert.cpp]
191[convert]
192[endsect]
193
194[section:references References]
195[import ../example/references.cpp]
196[references]
197[endsect]
198
199[section:limit Syntax Limitations]
200
201In most cases using an any has the same
202syntax as using the underlying object.
203However, there are a few cases where
204this is not possible to implement.
205An __any reference is proxy and cannot
206be used in contexts where a real
207reference is required. In particular,
208__forward_iterator does not create
209a conforming ForwardIterator (unless
210the value_type is fixed.) Another
211difference is that all operations
212which do not take at least one __any
213argument have to be passed the type
214information explicitly. Static member
215functions and constructors can fall in
216this category. All this means that generic
217algorithms might not work when applied to
218__any arguments.
219
220[endsect]
221
222[endsect]
223
224[section:examples Examples]
225
226[section:print_sequence A polymorphic range formatter]
227[import ../example/print_sequence.cpp]
228[print_sequence]
229[endsect]
230
231[section:printf A type-safe printf]
232[import ../example/printf.cpp]
233[printf]
234[endsect]
235
236[section:multifunction Boost.Function with multiple signatures]
237[import ../example/multifunction.cpp]
238[multifunction]
239[endsect]
240
241[endsect]
242
243[section:conceptdef Concept Definitions]
244
245A Concept defines a set of constraints on the types that
246are stored in an __any.
247
248There are three kinds of concepts.
249
250# The library defines a number of [link boost_typeerasure.predef predefined concepts].
251 Most of these are equivalent to user-defined concepts, but a few
252 require special handling.
253# Users can define their own primitive concepts as described below.
254 The macros __BOOST_TYPE_ERASURE_MEMBER and __BOOST_TYPE_ERASURE_FREE
255 define concepts of this form.
256# Any MPL Forward Sequence whose elements are
257 concepts is also a concept. This allows concepts
258 to be composed easily.
259
260Each primitive concept defines a single function.
261A primitive concept must be a specialization of a
262class template, with a static member function
263called `apply`, which will be executed when the
264function is dispatched by __call. The template
265can only take template type parameters. non-type
266template parameters and template template parameters
267are not allowed.
268
269The template parameters of the concept
270may involve placeholders. The following are
271considered.
272
273* Each template argument may be a cv and/or reference
274 qualified placeholder type.
275* If a template argument is a function type, its
276 arguments and return type may be cv/reference
277 qualified placeholders.
278
279Any other placeholders are ignored.
280
281A concept is instantiated by constructing an
282__any from a raw value or by constructing a __binding.
283When a concept is instantiated with a specific
284set of type bindings, each placeholder is bound
285to a cv-unqualified non-reference type. After
286replacing each placeholder in the template argument
287list with the type that it binds to, the following
288must hold.
289
290* The number of arguments of apply in the
291 bound concept must be the same as the number
292 of arguments in the unbound concept.
293* The arguments and return type of apply in the
294 bound concept can be derived from the corresponding
295 arguments and the return type in the unbound concept
296 as follows: If the argument in the unbound concept is a
297 placeholder with optional cv and reference
298 qualifiers, then the argument in the bound
299 concept can be found by replacing the placeholder.
300 Otherwise, the argument in the unbound concept
301 must be the same as the argument in the bound concept.
302
303 // Correct.
304 template<class T = _self>
305 struct foo1 {
306 static void apply(const T& t) { t.foo(); }
307 };
308
309 // Wrong. The signature of apply is different from the
310 // primary template
311 template<>
312 struct foo1<int> {
313 static void apply(int i);
314 };
315
316 // Wrong. A concept must be a template
317 struct foo2 {
318 static void apply(const _self&);
319 };
320
321 // Wrong. apply must be static
322 template<class T = _self>
323 struct foo3 {
324 void apply(const T&);
325 };
326
327 // Wrong. apply cannot be overloaded
328 template<class T = _self>
329 struct foo3 {
330 static void apply(T&);
331 static void apply(const T&);
332 };
333
334 // Wrong. Only top level placeholders are detected
335 template<class T>
336 struct foo4;
337 template<class T>
338 struct foo4<boost::mpl::vector<T> > {
339 static void apply(const T&);
340 };
341
342 // Wrong. Template template parameters are not allowed.
343 template<template<class> class T>
344 struct foo5
345 {
346 static void apply(T<int>&);
347 };
348
349[endsect]
350
351[section:predef Predefined Concepts]
352
353In the following tables, `T` and `U` are the types that the operation
354applies to, `R` is the result type. `T` always defaults
355to `_self` to match the default behavior of any. These
356concepts assume normal semantics. Thus, comparison
357operators always return bool, and references will be
358added to the arguments and results as appropriate.
359
360Except as otherwise noted, primitive concepts defined by
361the library can be specialized to provide concept maps.
362__copy_constructible, and the iterator concepts cannot
363be specialized because they are composites. __constructible,
364__destructible, __typeid_, and __same_type cannot be
365specialized because they require special handling in
366the library.
367
368[table:special Special Members
369 [[concept][notes]]
370 [[__constructible`<Sig>`][-]]
371 [[__copy_constructible`<T>`][-]]
372 [[__destructible`<T>`][-]]
373 [[__assignable`<T, U = T>`][-]]
374 [[__typeid_`<T>`][-]]
375]
376[table:unary Unary Operators
377 [[operator][concept][notes]]
378 [[`operator++`][__incrementable`<T>`][There is no separate post-increment]]
379 [[`operator--`][__decrementable`<T>`][There is no separate post-decrement]]
380 [[`operator*`][__dereferenceable`<R, T>`][`R` should usually be a reference]]
381 [[`operator~`][__complementable`<T, R = T>`][-]]
382 [[`operator-`][__negatable`<T, R = T>`][-]]
383]
384
385[table:binary Binary Operators
386 [[operator][concept][notes]]
387 [[`operator+`][__addable`<T, U = T, R = T>`][-]]
388 [[`operator-`][__subtractable`<T, U = T, R = T>`][-]]
389 [[`operator*`][__multipliable`<T, U = T, R = T>`][-]]
390 [[`operator/`][__dividable`<T, U = T, R = T>`][-]]
391 [[`operator%`][__modable`<T, U = T, R = T>`][-]]
392 [[`operator&`][__bitandable`<T, U = T, R = T>`][-]]
393 [[`operator|`][__bitorable`<T, U = T, R = T>`][-]]
394 [[`operator^`][__bitxorable`<T, U = T, R = T>`][-]]
395 [[`operator<<`][__left_shiftable`<T, U = T, R = T>`][-]]
396 [[`operator>>`][__right_shiftable`<T, U = T, R = T>`][-]]
397 [[`operator==` and `!=`][__equality_comparable`<T, U = T>`][`!=` is implemented in terms of `==`]]
398 [[`operator<`, `>`, `<=`, and `>=`][__less_than_comparable`<T, U = T>`][All are implemented in terms of `<`]]
399 [[`operator+=`][__add_assignable`<T, U = T>`][-]]
400 [[`operator-=`][__subtract_assignable`<T, U = T>`][-]]
401 [[`operator*=`][__multiply_assignable`<T, U = T>`][-]]
402 [[`operator/=`][__divide_assignable`<T, U = T>`][-]]
403 [[`operator%=`][__mod_assignable`<T, U = T>`][-]]
404 [[`operator&=`][__bitand_assignable`<T, U = T>`][-]]
405 [[`operator|=`][__bitor_assignable`<T, U = T>`][-]]
406 [[`operator^=`][__bitxor_assignable`<T, U = T>`][-]]
407 [[`operator<<=`][__left_shift_assignable`<T, U = T>`][-]]
408 [[`operator>>=`][__right_shift_assignable`<T, U = T>`][-]]
409 [[`operator<<`][__ostreamable`<Os = std::ostream, T = _self>`][-]]
410 [[`operator>>`][__istreamable`<Is = std::istream, T = _self>`][-]]
411]
412
413[table:misc Miscellaneous Operators
414 [[operator][concept][notes]]
415 [[`operator()`][__callable`<Sig, T>`][`Sig` should be a function type. T may be const qualified.]]
416 [[`operator[]`][__subscriptable`<R, T, N = std::ptrdiff_t>`][`R` should usually be a reference. `T` can be optionally const qualified.]]
417]
418
419[table:iterator Iterator Concepts
420 [[concept][notes]]
421 [[__iterator`<Traversal, T, Reference, Difference>`][Use __same_type to control the iterator's value type.]]
422 [[__forward_iterator`<T, Reference, Difference>`][-]]
423 [[__bidirectional_iterator`<T, Reference, Difference>`][-]]
424 [[__random_access_iterator`<T, Reference, Difference>`][-]]
425]
426
427[table:special Special Concepts
428 [[concept][notes]]
429 [[__same_type`<T>`][Indicates that two types are the same.]]
430]
431
432[endsect]
433
434[xinclude reference.xml]
435
436[section:rationale Rationale]
437
438[section Why do I have to specify the presence of a destructor explicitly?]
439When using references the destructor isn't needed.
440By not assuming it implicitly, we allow capturing
441types with private or protected destructors by reference.
442For the sake of consistency, it must be specified
443when capturing by value as well.
444[endsect]
445
446[section Why non-member functions?]
447The members of __any can be customized. By using
448free functions, we guarantee that we don't interfere
449with anything that a user might want.
450[endsect]
451
452[section:placeholder Why are the placeholders called `_a`, `_b` and not `_1` `_2`]
453
454An earlier version of the library used the names `_1`, `_2`, etc.
455instead of `_a`, `_b`, etc. This caused a certain amount
456of confusion because the numbered placeholders are
457already used with a somewhat different meaning by several
458other libraries including Boost/Std Bind, Boost.Phoenix,
459and Boost.MPL. I eventually decided that since the
460placeholders represented named parameters instead of positional parameters,
461letters were more appropriate than numbers.
462
463[endsect]
464
465[section:ref Why not use `boost::ref` for references?]
466
467Boost.Function allows you to use `boost::ref` to store
468a reference to a function object. However, in the
469general case treating references and values in the
470same way causes inconsistent behavior that is difficult
471to reason about. If Boost.TypeErasure handled references
472like this, then, when you copy an __any, you would have
473no idea whether the new object is a real copy or
474just a new reference to the same underlying object.
475Boost.Function can get away with it, because it doesn't
476expose any mutating operations on the stored function object.
477
478Another method that has been proposed is only to
479keep a reference the first time.
480
481 int i = 2;
482 any x = ref(i);
483 any y = x; // makes a copy
484
485Unfortunately, this doesn't handle all use cases,
486as there is no reliable way to return such a reference
487from a function. In addition it adds overhead whether
488it's needed or not, as we would have to add a flag
489to any to keep track of whether or not it is storing
490a reference. (The alternate method of storing this
491in the "`clone`" method in the vtable is impossibly complex
492to implement given the decoupled vtables that
493Boost.TypeErasure uses and it still adds overhead.).
494
495[endsect]
496
497[endsect]
498
499[section:future Future Work]
500
501These are just some ideas. There is absolutely no
502guarantee that any of them will ever be implemented.
503
504* Use SBO.
505* Allow more control over vtable layout.
506* Attempt to reuse sub-tables in conversions.
507* Allow "dynamic_cast". This requires creating
508 a global registry of concept mappings.
509* Optimize the compile-time cost.
510
511[endsect]
512
513
514[section:acknowledgements Acknowledgements]
515
516The name `any` and an early ancestor of my placeholder
517system were taken from Alexander Nasonov's DynamicAny library.
518
519Thanks to review manager, Lorenzo Caminiti
520and all who participated in the formal review:
521
522* Christophe Henry
523* Paul Bristow
524* Karsten Ahnert
525* Pete Bartlett
526* Sebastian Redl
527* Hossein Haeri
528* Trigve Siver
529* Julien Nitard
530* Eric Niebler
531* Fabio Fracassi
532* Joel de Guzman
533* Alec Chapman
534* Larry Evans
535* Vincente J. Botet Escriba
536* Marcus Werle
537* Andrey Semashev
538* Dave Abrahams
539* Thomas Jordan
540
541[endsect]
542
543[section:related Related Work]
544
545There are a number of similar libraries in existence. I'm aware
546of at least three.
547
548* [@http://www.coderage.com/interfaces/ Boost.Interfaces] by Jonathan Turkanis
549* [@http://stlab.adobe.com/group__poly__related.html Adobe Poly]
550* [@http://cpp-experiment.sourceforge.net/boost/libs/dynamic_any/doc/ Boost.dynamic_any] by Alexander Nasonov
551
552[endsect]