Header boost/polymorphic_cast.hpp Documentation

# Header boost/polymorphic_cast.hpp

## Cast Functions

The header boost/polymorphic_cast.hpp provides `polymorphic_cast` and `polymorphic_downcast` function templates designed to complement the C++ built-in casts.

The header boost/polymorphic_pointer_cast.hpp provides `polymorphic_pointer_cast` and `polymorphic_pointer_downcast` function templates.

The program cast_test.cpp can be used to verify these function templates work as expected.

### Polymorphic casts

Pointers to polymorphic objects (objects of classes which define at least one virtual function) are sometimes downcast or crosscast. Downcasting means casting from a base class to a derived class. Crosscasting means casting across an inheritance hierarchy diagram, such as from one base to the other in a `Y` diagram hierarchy.

Such casts can be done with old-style casts, but this approach is never to be recommended. Old-style casts are sorely lacking in type safety, suffer poor readability, and are difficult to locate with search tools.

The C++ built-in `static_cast` can be used for efficiently downcasting pointers to polymorphic objects, but provides no error detection for the case where the pointer being cast actually points to the wrong derived class. The `polymorphic_downcast` template retains the efficiency of `static_cast` for non-debug compilations, but for debug compilations adds safety via an assert() that a `dynamic_cast` succeeds.

The C++ built-in `dynamic_cast` can be used for downcasts and crosscasts of pointers to polymorphic objects, but error notification in the form of a returned value of 0 is inconvenient to test, or worse yet, easy to forget to test. The throwing form of `dynamic_cast`, which works on references, can be used on pointers through the ugly expression &`dynamic_cast<T&>(*p)`, which causes undefined behavior if `p` is `0`. The `polymorphic_cast` template performs a `dynamic_cast` on a pointer, and throws an exception if the `dynamic_cast` returns 0.

A `polymorphic_downcast` should be used for downcasts that you are certain should succeed. Error checking is only performed in translation units where `NDEBUG` is not defined, via

      assert( dynamic_cast<Derived>(x) == x )

where `x` is the source pointer. This approach ensures that not only is a non-zero pointer returned, but also that it is correct in the presence of multiple inheritance. Attempts to crosscast using `polymorphic_downcast` will fail to compile. Warning: Because `polymorphic_downcast` uses assert(), it violates the One Definition Rule (ODR) if NDEBUG is inconsistently defined across translation units. [See ISO Std 3.2]

For crosscasts, or when the success of a cast can only be known at runtime, or when efficiency is not important, `polymorphic_cast` is preferred.

The C++ built-in `dynamic_cast` must be used to cast references rather than pointers. 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.

While `polymorphic_downcast` and `polymorphic_cast` work with built-in pointer types only, `polymorphic_pointer_downcast` and `polymorphic_pointer_cast` are more generic versions with support for any pointer type for which the following expressions would be valid:

For `polymorphic_pointer_downcast`:

`static_pointer_cast<Derived>(p);
dynamic_pointer_cast<Derived>(p);`

For `polymorphic_pointer_cast`:

`dynamic_pointer_cast<Derived>(p);
!p; // conversion to bool with negation`

This includes C++ built-in pointers, `std::shared_ptr, boost::shared_ptr, boost::intrusive_ptr`, etc.

### polymorphic_cast, polymorphic_downcast, polymorphic_pointer_cast and polymorphic_pointer_downcast synopsis

>     namespace boost {

>     template <class Derived, class Base>
>     inline Derived polymorphic_cast(Base* x);
>     // Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
>     // Returns: dynamic_cast<Derived>(x)

>     template <class Derived, class Base>
>     inline Derived polymorphic_downcast(Base* x);
>     // Effects: assert( dynamic_cast<Derived>(x) == x );
>     // Returns: static_cast<Derived>(x)

>     template <class Derived, class Base>
>     inline auto polymorphic_pointer_cast(Base x);
>     // Throws: std::bad_cast if ( dynamic_pointer_cast<Derived>(x) == 0 )
>     // Returns: dynamic_pointer_cast<Derived>(x)

>     template <class Derived, class Base>
>     inline auto polymorphic_pointer_downcast(Base x);
>     // Effects: assert( dynamic_pointer_cast<Derived>(x) == x );
>     // Returns: static_pointer_cast<Derived>(x)

>     }

### polymorphic_downcast example

>     #include <boost/polymorphic_cast.hpp>
>     ...
>     class Fruit { public: virtual ~Fruit(){}; ... };
>     class Banana : public Fruit { ... };
>     ...
>     void f( Fruit * fruit ) {
>     // ... logic which leads us to believe it is a Banana
>       Banana * banana = boost::polymorphic_downcast<Banana*>(fruit);
>       ...

### polymorphic_pointer_downcast example

>     #include <boost/polymorphic_pointer_cast.hpp>

>     class Fruit { public: virtual ~Fruit(){} };
>     class Banana : public Fruit {};

>     // use one of these:

>     typedef Fruit* FruitPtr;
>     typedef std::shared_ptr<Fruit> FruitPtr;
>     typedef boost::shared_ptr<Fruit> FruitPtr;
>     typedef boost::intrusive_ptr<Fruit> FruitPtr;

>     void f(FruitPtr fruit)
>     {
>       // ... logic which leads us to believe it is a banana
>       auto banana = boost::polymorphic_pointer_downcast<Banana>(fruit);
>       ...
>     }

### History

`polymorphic_cast` was suggested by Bjarne Stroustrup in "The C++ Programming Language".
`polymorphic_downcast` was contributed by Dave Abrahams.
`polymorphic_pointer_downcast` was contributed by Boris Rasin and `polymorphic_pointer_cast` by Antony Polukhin.
An old `numeric_cast` that was contributed by Kevlin Henney is now superseeded by the Boost Numeric Conversion Library

Revised June 23, 2005

© Copyright boost.org 1999. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)