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