type_erasure.qbk 20 KB

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