1 [library Boost.TypeErasure
3 [authors [Watanabe, Steven]]
4 [copyright 2011-2013 Steven Watanabe]
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])
10 [purpose Runtime polymorphism based on concepts]
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]]
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]]
69 [def __BOOST_TYPE_ERASURE_MEMBER [macroref BOOST_TYPE_ERASURE_MEMBER]]
70 [def __BOOST_TYPE_ERASURE_FREE [macroref BOOST_TYPE_ERASURE_FREE]]
72 [section:introduction Introduction]
74 The Boost.TypeErasure library provides runtime polymorphism
75 in C++ that is more flexible than that provided by the
78 C++ has two distinct kinds of polymorphism,
79 virtual functions and templates, each of which has
80 its own advantages and disadvantages.
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
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.
116 The Boost.TypeErasure library combines the superior
117 abstraction capabilities of templates, with the
118 runtime flexibility of virtual functions.
120 Boost includes several special cases of this kind
123 * `boost::any` for CopyConstructible types.
124 * `boost::function` for objects that can be called like functions.
125 * Boost.Range provides `any_iterator`.
127 Boost.TypeErasure generalizes this to support arbitrary
128 requirements and provides a
129 [link boost_typeerasure.predef predefined set of common concepts]
133 [section:reading How to read this documentation]
135 To avoid excessive verbosity, all the examples
136 assume that a few using directives are in place.
138 namespace mpl = boost::mpl;
139 using namespace boost::type_erasure;
143 [section:basic Basic Usage]
144 [import ../example/basic.cpp]
148 [section Composing Concepts]
149 [import ../example/compose.cpp]
153 [section:multi Functions with Multiple Arguments]
154 [import ../example/multi.cpp]
158 [section:concept Concepts in Depth]
160 [section:custom Defining Custom Concepts]
161 [import ../example/custom.cpp]
165 [section:overload Overloading]
166 [import ../example/overload.cpp]
170 [section:concept_map Concept Maps]
171 [import ../example/concept_map.cpp]
175 [section:overload Associated Types]
176 [import ../example/associated.cpp]
182 [section:any Using Any]
184 [section:construction Construction]
185 [import ../example/construction.cpp]
189 [section Conversions]
190 [import ../example/convert.cpp]
194 [section:references References]
195 [import ../example/references.cpp]
199 [section:limit Syntax Limitations]
201 In most cases using an any has the same
202 syntax as using the underlying object.
203 However, there are a few cases where
204 this is not possible to implement.
205 An __any reference is proxy and cannot
206 be used in contexts where a real
207 reference is required. In particular,
208 __forward_iterator does not create
209 a conforming ForwardIterator (unless
210 the value_type is fixed.) Another
211 difference is that all operations
212 which do not take at least one __any
213 argument have to be passed the type
214 information explicitly. Static member
215 functions and constructors can fall in
216 this category. All this means that generic
217 algorithms might not work when applied to
224 [section:examples Examples]
226 [section:print_sequence A polymorphic range formatter]
227 [import ../example/print_sequence.cpp]
231 [section:printf A type-safe printf]
232 [import ../example/printf.cpp]
236 [section:multifunction Boost.Function with multiple signatures]
237 [import ../example/multifunction.cpp]
243 [section:conceptdef Concept Definitions]
245 A Concept defines a set of constraints on the types that
246 are stored in an __any.
248 There are three kinds of concepts.
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.
260 Each primitive concept defines a single function.
261 A primitive concept must be a specialization of a
262 class template, with a static member function
263 called `apply`, which will be executed when the
264 function is dispatched by __call. The template
265 can only take template type parameters. non-type
266 template parameters and template template parameters
269 The template parameters of the concept
270 may involve placeholders. The following are
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.
279 Any other placeholders are ignored.
281 A concept is instantiated by constructing an
282 __any from a raw value or by constructing a __binding.
283 When a concept is instantiated with a specific
284 set of type bindings, each placeholder is bound
285 to a cv-unqualified non-reference type. After
286 replacing each placeholder in the template argument
287 list with the type that it binds to, the following
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.
304 template<class T = _self>
306 static void apply(const T& t) { t.foo(); }
309 // Wrong. The signature of apply is different from the
313 static void apply(int i);
316 // Wrong. A concept must be a template
318 static void apply(const _self&);
321 // Wrong. apply must be static
322 template<class T = _self>
324 void apply(const T&);
327 // Wrong. apply cannot be overloaded
328 template<class T = _self>
330 static void apply(T&);
331 static void apply(const T&);
334 // Wrong. Only top level placeholders are detected
338 struct foo4<boost::mpl::vector<T> > {
339 static void apply(const T&);
342 // Wrong. Template template parameters are not allowed.
343 template<template<class> class T>
346 static void apply(T<int>&);
351 [section:predef Predefined Concepts]
353 In the following tables, `T` and `U` are the types that the operation
354 applies to, `R` is the result type. `T` always defaults
355 to `_self` to match the default behavior of any. These
356 concepts assume normal semantics. Thus, comparison
357 operators always return bool, and references will be
358 added to the arguments and results as appropriate.
360 Except as otherwise noted, primitive concepts defined by
361 the library can be specialized to provide concept maps.
362 __copy_constructible, and the iterator concepts cannot
363 be specialized because they are composites. __constructible,
364 __destructible, __typeid_, and __same_type cannot be
365 specialized because they require special handling in
368 [table:special Special Members
370 [[__constructible`<Sig>`][-]]
371 [[__copy_constructible`<T>`][-]]
372 [[__destructible`<T>`][-]]
373 [[__assignable`<T, U = T>`][-]]
374 [[__typeid_`<T>`][-]]
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>`][-]]
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>`][-]]
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.]]
419 [table:iterator Iterator Concepts
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>`][-]]
427 [table:special Special Concepts
429 [[__same_type`<T>`][Indicates that two types are the same.]]
434 [xinclude reference.xml]
436 [section:rationale Rationale]
438 [section Why do I have to specify the presence of a destructor explicitly?]
439 When using references the destructor isn't needed.
440 By not assuming it implicitly, we allow capturing
441 types with private or protected destructors by reference.
442 For the sake of consistency, it must be specified
443 when capturing by value as well.
446 [section Why non-member functions?]
447 The members of __any can be customized. By using
448 free functions, we guarantee that we don't interfere
449 with anything that a user might want.
452 [section:placeholder Why are the placeholders called `_a`, `_b` and not `_1` `_2`]
454 An earlier version of the library used the names `_1`, `_2`, etc.
455 instead of `_a`, `_b`, etc. This caused a certain amount
456 of confusion because the numbered placeholders are
457 already used with a somewhat different meaning by several
458 other libraries including Boost/Std Bind, Boost.Phoenix,
459 and Boost.MPL. I eventually decided that since the
460 placeholders represented named parameters instead of positional parameters,
461 letters were more appropriate than numbers.
465 [section:ref Why not use `boost::ref` for references?]
467 Boost.Function allows you to use `boost::ref` to store
468 a reference to a function object. However, in the
469 general case treating references and values in the
470 same way causes inconsistent behavior that is difficult
471 to reason about. If Boost.TypeErasure handled references
472 like this, then, when you copy an __any, you would have
473 no idea whether the new object is a real copy or
474 just a new reference to the same underlying object.
475 Boost.Function can get away with it, because it doesn't
476 expose any mutating operations on the stored function object.
478 Another method that has been proposed is only to
479 keep a reference the first time.
483 any y = x; // makes a copy
485 Unfortunately, this doesn't handle all use cases,
486 as there is no reliable way to return such a reference
487 from a function. In addition it adds overhead whether
488 it's needed or not, as we would have to add a flag
489 to any to keep track of whether or not it is storing
490 a reference. (The alternate method of storing this
491 in the "`clone`" method in the vtable is impossibly complex
492 to implement given the decoupled vtables that
493 Boost.TypeErasure uses and it still adds overhead.).
499 [section:future Future Work]
501 These are just some ideas. There is absolutely no
502 guarantee that any of them will ever be implemented.
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.
514 [section:acknowledgements Acknowledgements]
516 The name `any` and an early ancestor of my placeholder
517 system were taken from Alexander Nasonov's DynamicAny library.
519 Thanks to review manager, Lorenzo Caminiti
520 and all who participated in the formal review:
535 * Vincente J. Botet Escriba
543 [section:related Related Work]
545 There are a number of similar libraries in existence. I'm aware
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