Initial commit after public review (note change in library name per review)

[SVN r8516]
This commit is contained in:
Beman Dawes 2001-01-06 16:47:36 +00:00
parent cba48df8e3
commit 6a0c3e92a0
2 changed files with 0 additions and 301 deletions

148
cast.htm
View File

@ -1,148 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Header boost/cast.hpp Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Header
<a href="../../boost/cast.hpp">boost/cast.hpp</a></h1>
<h2><a name="Cast Functions">Cast Functions</a></h2>
<p>The <code>header <a href="../../boost/cast.hpp">boost/cast.hpp</a></code>
provides <a href="#Polymorphic_cast"><b>polymorphic_cast</b></a>, <a href="#Polymorphic_cast"><b>polymorphic_downcast</b></a>,
and <a href="#numeric_cast"><b>numeric_cast</b></a> template functions designed
to complement the C++ Standard's built-in casts.</p>
<p>The program&nbsp;<a href="cast_test.cpp">cast_test.cpp</a> can be used to
verify these function templates work as expected.</p>
<p><b>polymorphic_cast</b> was suggested by Bjarne Stroustrup in &quot;The C++
Programming Language&quot;.<br>
<b>polymorphic_downcast</b> was contributed by <a href="../../people/dave_abrahams.htm">Dave
Abrahams</a>.<b><br>
numeric_cast</b> was contributed by <a href="../../people/kevlin_henney.htm">Kevlin
Henney</a>.</p>
<h3>Namespace synopsis</h3>
<blockquote>
<pre>namespace boost {
namespace cast {
// all synopsis below included here
}
using ::boost::cast::polymorphic_cast;
using ::boost::cast::polymorphic_downcast;
using ::boost::cast::bad_numeric_cast;
using ::boost::cast::numeric_cast;
}</pre>
</blockquote>
<h3><a name="Polymorphic_cast">Polymorphic casts</a></h3>
<p>Pointers to polymorphic objects (objects of classes which define at least one
virtual function) are sometimes downcast or crosscast.&nbsp; Downcasting means
casting from a base class to a derived class.&nbsp; Crosscasting means casting
across an inheritance hierarchy diagram, such as from one base to the other in a
<b>Y</b> diagram hierarchy.</p>
<p>Such casts can be done with old-style casts, but this approach is never to be
recommended.&nbsp; Old-style casts are sorely lacking in type safety, suffer
poor readability, and are difficult to locate with search tools.</p>
<p>The C++ built-in <b>static_cast</b> 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 <b>polymorphic_downcast</b>
template retains the efficiency of <b>static_cast</b> for non-debug
compilations, but for debug compilations adds safety via an assert() that a <b>dynamic_cast</b>
succeeds.&nbsp;<b>&nbsp;</b></p>
<p>The C++ built-in <b>dynamic_cast</b> 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.&nbsp; The <b>polymorphic_cast</b> template performs a <b>dynamic_cast</b>,
and throws an exception if the <b>dynamic_cast</b> returns 0.</p>
<p>A <b>polymorphic_downcast</b> 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, <b>polymorphic_cast</b> is
preferred.&nbsp; It must also be used for crosscasts.&nbsp; It does an assert(
dynamic_cast&lt;Derived&gt;(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. .<b> Warning:</b>: Because <b>polymorphic_downcast</b>
uses assert(), it violates the One Definition Rule if NDEBUG is inconsistently
defined across translation units.</p>
<p>The C++ built-in <b>dynamic_cast</b> must be used to cast references rather
than pointers.&nbsp; 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.</p>
<h3>polymorphic_cast and polymorphic_downcast synopsis</h3>
<blockquote>
<pre>template &lt;class Derived, class Base&gt;
inline Derived polymorphic_cast(Base* x);
// Throws: std::bad_cast if ( dynamic_cast&lt;Derived&gt;(x) == 0 )
// Returns: dynamic_cast&lt;Derived&gt;(x)
template &lt;class Derived, class Base&gt;
inline Derived polymorphic_downcast(Base* x);
// Effects: assert( dynamic_cast&lt;Derived&gt;(x) == x );
// Returns: static_cast&lt;Derived&gt;(x)</pre>
</blockquote>
<h3>polymorphic_downcast example</h3>
<blockquote>
<pre>#include &lt;boost/cast.hpp&gt;
...
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&lt;Banana*&gt;(fruit);
...</pre>
</blockquote>
<h3><a name="numeric_cast">numeric_cast</a></h3>
<p>A <b>static_cast</b>, <b>implicit_cast</b> or implicit conversion will not
detect failure to preserve range for numeric casts. The <b>numeric_cast</b>
template function are similar to <b>static_cast</b> 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.</p>
<p>The requirements on the argument and result types are:</p>
<blockquote>
<ul>
<li>Both argument and result types are CopyConstructible [20.1.3].</li>
<li>Both argument and result types are Numeric, defined by <code>std::numeric_limits&lt;&gt;::is_specialized</code>
being true.</li>
<li>The argument can be converted to the result type using <b>static_cast</b>.</li>
</ul>
</blockquote>
<h3>numeric_cast synopsis</h3>
<blockquote>
<pre>class bad_numeric_cast : public std::bad_cast {...};
template&lt;typename Target, typename Source&gt;
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&lt;Target&gt;(arg)</pre>
</blockquote>
<h3>numeric_cast example</h3>
<blockquote>
<pre>#include &lt;boost/cast.hpp&gt;
using namespace boost::cast;
void ariane(double vx)
{
...
unsigned short dx = numeric_cast&lt;unsigned short&gt;(vx);
...
}</pre>
</blockquote>
<h3>numeric_cast rationale</h3>
<p>The form of the throws condition is specified so that != is not a required
operation.</p>
<hr>
<p>Revised&nbsp; <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
-->28 June, 2000<!--webbot bot="Timestamp" endspan i-checksum="19846"
--></p>
<p>© 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 &quot;as is&quot; without express or
implied warranty, and with no claim as to its suitability for any purpose.</p>
</body>
</html>

View File

@ -1,153 +0,0 @@
// boost utility cast test program -----------------------------------------//
// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 28 Jun 00 implicit_cast removed (Beman Dawes)
// 30 Aug 99 value_cast replaced by numeric_cast
// 3 Aug 99 Initial Version
#include <iostream>
#include <climits>
#include <limits>
#include <boost/cast.hpp>
# if SCHAR_MAX == LONG_MAX
# error "This test program doesn't work if SCHAR_MAX == LONG_MAX"
# endif
using namespace boost;
using std::cout;
namespace
{
struct Base
{
virtual char kind() { return 'B'; }
};
struct Base2
{
virtual char kind2() { return '2'; }
};
struct Derived : public Base, Base2
{
virtual char kind() { return 'D'; }
};
}
int main( int argc, char * argv[] )
{
cout << "Usage: test_casts [n], where n omitted or is:\n"
" 1 = execute #1 assert failure (#ifndef NDEBUG)\n"
" 2 = execute #2 assert failure (#ifndef NDEBUG)\n"
"Example: test_casts 2\n\n";
# ifdef NDEBUG
cout << "NDEBUG is defined\n";
# else
cout << "NDEBUG is not defined\n";
# endif
cout << "\nBeginning tests...\n";
// test polymorphic_cast ---------------------------------------------------//
// tests which should succeed
Base * base = new Derived;
Base2 * base2 = 0;
Derived * derived = 0;
derived = polymorphic_downcast<Derived*>( base ); // downcast
assert( derived->kind() == 'D' );
derived = 0;
derived = polymorphic_cast<Derived*>( base ); // downcast, throw on error
assert( derived->kind() == 'D' );
base2 = polymorphic_cast<Base2*>( base ); // crosscast
assert( base2->kind2() == '2' );
// tests which should result in errors being detected
int err_count = 0;
base = new Base;
if ( argc > 1 && *argv[1] == '1' )
{ derived = polymorphic_downcast<Derived*>( base ); } // #1 assert failure
bool caught_exception = false;
try { derived = polymorphic_cast<Derived*>( base ); }
catch (std::bad_cast)
{ cout<<"caught bad_cast\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
// the following is just so generated code can be inspected
if ( derived->kind() == 'B' ) ++err_count;
// test implicit_cast and numeric_cast -------------------------------------//
// tests which should succeed
long small_value = 1;
long small_negative_value = -1;
long large_value = std::numeric_limits<long>::max();
long large_negative_value = std::numeric_limits<long>::min();
signed char c = 0;
c = large_value; // see if compiler generates warning
c = numeric_cast<signed char>( small_value );
assert( c == 1 );
c = 0;
c = numeric_cast<signed char>( small_value );
assert( c == 1 );
c = 0;
c = numeric_cast<signed char>( small_negative_value );
assert( c == -1 );
// These tests courtesy of Joe R NWP Swatosh<joe.r.swatosh@usace.army.mil>
assert( 0.0f == numeric_cast<float>( 0.0 ) );
assert( 0.0 == numeric_cast<double>( 0.0 ) );
// tests which should result in errors being detected
caught_exception = false;
try { c = numeric_cast<signed char>( large_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #1\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
caught_exception = false;
try { c = numeric_cast<signed char>( large_negative_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #2\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
unsigned long ul;
caught_exception = false;
try { ul = numeric_cast<unsigned long>( large_negative_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #3\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
caught_exception = false;
try { ul = numeric_cast<unsigned long>( small_negative_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #4\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
caught_exception = false;
try { numeric_cast<int>( std::numeric_limits<double>::max() ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #5\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
cout << err_count << " errors detected\nTest "
<< (err_count==0 ? "passed\n" : "failed\n");
return err_count;
} // main