conversion.qbk 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. [/
  2. Copyright 2016 Mikhail Maximov.
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)
  5. ]
  6. [article The Conversion Library
  7. [quickbook 1.6]
  8. [compatibility-mode 1.5]
  9. [id conversion]
  10. [version 1.6]
  11. [authors [Stroustrup, Bjarne], [Abrahams, Dave], [Rasin, Boris], [Polukhin, Antony]]
  12. [copyright 2001 Beman Dawes, 2014-2019 Antony Polukhin]
  13. [license
  14. Distributed under the Boost Software License, Version 1.0.
  15. (See accompanying file LICENSE_1_0.txt or copy at
  16. [@http://www.boost.org/LICENSE_1_0.txt])
  17. ]
  18. [source-mode teletype]
  19. ]
  20. [/ QuickBook Document version 1.5 ]
  21. [/ Dec, 2016 ]
  22. [section Description]
  23. The Conversion Library improves program safety and clarity by performing
  24. otherwise messy conversions. It includes cast-style function templates designed
  25. to complement the C++ Standard's built-in casts.
  26. To reduce coupling, particularly to standard library IOStreams,
  27. the Boost Conversion Library is supplied by several headers:
  28. # The [@boost:boost/polymorphic_cast.hpp boost/polymorphic_cast.hpp] header
  29. provides [link polymorphic_cast `polymorphic_cast<>`] and
  30. [link polymorphic_downcast `polymorphic_downcast<>`]
  31. to perform safe casting between polymorphic types.
  32. # The [@boost:boost/polymorphic_pointer_cast.hpp boost/polymorphic_pointer_cast.hpp] header
  33. provides [link polymorphic_pointer_cast `polymorphic_pointer_cast<>`] and
  34. [link polymorphic_pointer_cast `polymorphic_pointer_downcast<>`]
  35. # The [@boost:boost/implicit_cast.hpp boost/implicit_cast.hpp] header provides `implicit_cast<>`
  36. to perform implicit casts only (no down-cast, no void*->T*, no U->T if T has only explicit constructors for U).
  37. # The [@boost:boost/lexical_cast.hpp boost/lexical_cast.hpp] header
  38. provides [@boost:libs/lexical_cast/doc/html/index.html `lexical_cast<>`] general literal text conversions, such as an `int` represented as a `string`, or vice-versa.
  39. [endsect]
  40. [section Polymorphic casts]
  41. Pointers to polymorphic objects (objects of classes which define at
  42. least one virtual function) are sometimes downcast or crosscast.
  43. Downcasting means casting from a base class to a derived class.
  44. Crosscasting means casting across an inheritance hierarchy diagram, such
  45. as from one base to the other in a [^Y] diagram hierarchy.
  46. Such casts can be done with old-style casts, but this approach is
  47. never to be recommended. Old-style casts are sorely lacking in type
  48. safety, suffer poor readability, and are difficult to locate with search
  49. tools.
  50. [#polymorphic_downcast]
  51. The C++ built-in `static_cast` can be used for efficiently
  52. downcasting pointers to polymorphic objects, but provides no error
  53. detection for the case where the pointer being cast actually points to
  54. the wrong derived class. The `polymorphic_downcast` template retains
  55. the efficiency of `static_cast` for non-debug compilations, but for
  56. debug compilations adds safety via an `assert()` that a `dynamic_cast`
  57. succeeds.
  58. A `polymorphic_downcast` should be used for
  59. downcasts that you are certain should succeed. Error checking is
  60. only performed in translation units where `NDEBUG` is
  61. not defined, via
  62. ```
  63. assert( dynamic_cast<Derived>(x) == x )
  64. ```
  65. where `x` is the source pointer. This approach
  66. ensures that not only is a non-zero pointer returned, but also
  67. that it is correct in the presence of multiple inheritance.
  68. Attempts to crosscast using `polymorphic_downcast` will
  69. fail to compile.
  70. [warning Because `polymorphic_downcast` uses `assert()`, it
  71. violates the One Definition Rule (ODR) if NDEBUG is inconsistently
  72. defined across translation units. See ISO Std 3.2]
  73. [#polymorphic_cast]
  74. The C++ built-in `dynamic_cast` can be used for downcasts and
  75. crosscasts of pointers to polymorphic objects, but error notification in
  76. the form of a returned value of 0 is inconvenient to test, or worse yet,
  77. easy to forget to test. The throwing form of `dynamic_cast`, which
  78. works on references, can be used on pointers through the ugly expression
  79. `&dynamic_cast<T&>(*p)`, which causes undefined
  80. behavior if `p` is `0`. The `polymorphic_cast`
  81. template performs a `dynamic_cast` on a pointer, and throws an
  82. exception if the `dynamic_cast` returns 0.
  83. For crosscasts, or when the success of a cast can only be known at runtime,
  84. or when efficiency is not important, `polymorphic_cast` is preferred.
  85. The C++ built-in `dynamic_cast` must be used to cast references rather than pointers.
  86. It is also the only cast that can be used to check whether a given interface is supported; in that case a return of 0 isn't an error condition.
  87. [#polymorphic_pointer_cast]
  88. While `polymorphic_downcast` and `polymorphic_cast` work with built-in pointer types only,
  89. `polymorphic_pointer_downcast` and `polymorphic_pointer_cast` are more generic versions
  90. with support for any pointer type for which the following expressions would be valid:
  91. For `polymorphic_pointer_downcast`:
  92. ```
  93. static_pointer_cast<Derived>(p);
  94. dynamic_pointer_cast<Derived>(p);
  95. ```
  96. For `polymorphic_pointer_cast`:
  97. ```
  98. dynamic_pointer_cast<Derived>(p);
  99. !p; // conversion to bool with negation
  100. ```
  101. This includes C++ built-in pointers, `std::shared_ptr`,
  102. `boost::shared_ptr`, `boost::intrusive_ptr`, etc.
  103. [endsect]
  104. [section `polymorphic_cast`, `polymorphic_downcast`, `polymorphic_pointer_cast` and `polymorphic_pointer_downcast` synopsis]
  105. ```
  106. namespace boost {
  107. template <class Derived, class Base>
  108. inline Derived polymorphic_cast(Base* x);
  109. // Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
  110. // Returns: dynamic_cast<Derived>(x)
  111. template <class Derived, class Base>
  112. inline Derived polymorphic_downcast(Base* x);
  113. // Effects: assert( dynamic_cast<Derived>(x) == x );
  114. // Returns: static_cast<Derived>(x)
  115. template <class Derived, class Base>
  116. inline auto polymorphic_pointer_cast(Base x);
  117. // Throws: std::bad_cast if ( dynamic_pointer_cast<Derived>(x) == 0 )
  118. // Returns: dynamic_pointer_cast<Derived>(x)
  119. template <class Derived, class Base>
  120. inline auto polymorphic_pointer_downcast(Base x);
  121. // Effects: assert( dynamic_pointer_cast<Derived>(x) == x );
  122. // Returns: static_pointer_cast<Derived>(x)
  123. }
  124. ```
  125. [endsect]
  126. [section `polymorphic_downcast` example]
  127. ```
  128. #include <boost/polymorphic_cast.hpp>
  129. ...
  130. class Fruit { public: virtual ~Fruit(){}; ... };
  131. class Banana : public Fruit { ... };
  132. ...
  133. void f( Fruit * fruit ) {
  134. // ... logic which leads us to believe it is a Banana
  135. Banana * banana = boost::polymorphic_downcast<Banana*>(fruit);
  136. ...
  137. }
  138. ```
  139. [endsect]
  140. [section `polymorphic_pointer_downcast` example]
  141. ```
  142. #include <boost/polymorphic_pointer_cast.hpp>
  143. class Fruit { public: virtual ~Fruit(){} };
  144. class Banana : public Fruit {};
  145. // use one of these:
  146. typedef Fruit* FruitPtr;
  147. typedef std::shared_ptr<Fruit> FruitPtr;
  148. typedef boost::shared_ptr<Fruit> FruitPtr;
  149. typedef boost::intrusive_ptr<Fruit> FruitPtr;
  150. void f(FruitPtr fruit) {
  151. // ... logic which leads us to believe it is a banana
  152. auto banana = boost::polymorphic_pointer_downcast<Banana>(fruit);
  153. ...
  154. }
  155. ```
  156. [endsect]
  157. [section History]
  158. `polymorphic_cast` was suggested by Bjarne Stroustrup in "The C++ Programming Language".
  159. `polymorphic_downcast` was contributed by [@http://www.boost.org/people/dave_abrahams.htm Dave Abrahams].
  160. `polymorphic_pointer_downcast` was contributed by [@http://www.boost.org/people/boris_rasin.htm Boris Rasin]
  161. and `polymorphic_pointer_cast` by Antony Polukhin.
  162. An old `numeric_cast` that was contributed by [@http://www.boost.org/people/kevlin_henney.htm Kevlin Henney]
  163. is now superseeded by the [@boost:numeric_conversion/doc/html/html/boost_numericconversion/improved_numeric_cast__.html Boost Numeric Conversion Library]
  164. [endsect]