...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
The header boost/cast.hpp provides
polymorphic_cast and
polymorphic_downcast
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.
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.
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) }
#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); ...
polymorphic_cast
was suggested by Bjarne Stroustrup in "The C++
Programming Language".
polymorphic_downcast
was contributed by Dave Abrahams.
that was contributed by Kevlin Henney is now superseeded by the Boost Numeric Conversion Library
An old
numeric_cast
Revised June 23, 2005
© 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.