Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Click here to view the latest version of this page.

Header boost/cast.hpp

Cast Functions

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

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 is preferred when debug-mode tests will cover 100% of the object types possibly cast and when non-debug-mode efficiency is an issue. If these two conditions are not present, polymorphic_cast is preferred. It must also be used for crosscasts. It does an assert( dynamic_cast<Derived>(x) == x ) where x is the base pointer, ensuring that not only is a non-zero pointer returned, but also that it correct in the presence of multiple inheritance. 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]

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.

polymorphic_cast and polymorphic_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)

}

polymorphic_downcast example

#include <boost/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);
  ...

numeric_cast

A static_cast or implicit conversion will not detect failure to preserve range for numeric casts. The numeric_cast function templates are similar to static_cast and certain (dubious) implicit conversions in this respect, except that they detect loss of numeric range. An exception is thrown when a runtime value-preservation check fails.

The requirements on the argument and result types are:

numeric_cast synopsis

namespace boost {

class bad_numeric_cast : public std::bad_cast {...};

template<typename Target, typename Source>
  inline Target numeric_cast(Source arg);
    // Throws:  bad_numeric_cast unless, in converting arg from Source to Target,
    //          there is no loss of negative range, and no underflow, and no
    //          overflow, as determined by std::numeric_limits
    // Returns: static_cast<Target>(arg)

}

numeric_cast example

#include <boost/cast.hpp>
using namespace boost::cast;

void ariane(double vx)
{
    ...
    unsigned short dx = numeric_cast<unsigned short>(vx);
    ...
}

numeric_cast rationale

The form of the throws condition is specified so that != is not a required operation.

History

polymorphic_cast was suggested by Bjarne Stroustrup in "The C++ Programming Language".
polymorphic_downcast was contributed by Dave Abrahams.
numeric_cast
was contributed by Kevlin Henney.


Revised 06 January, 2001

© Copyright boost.org 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.