Compare commits

..

1 Commits

Author SHA1 Message Date
nobody 8c6b836076 This commit was manufactured by cvs2svn to create tag
'Version_1_20_0'.

[SVN r8518]
2001-01-06 18:30:47 +00:00
6 changed files with 118 additions and 190 deletions
+12 -17
View File
@@ -1,5 +1,3 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
@@ -11,49 +9,46 @@
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">Header
<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 header <a href="../../boost/cast.hpp">boost/cast.hpp</a>
<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> function templates designed
to complement the C++ built-in casts.</p>
<p>The program <a href="cast_test.cpp">cast_test.cpp</a> can be used to
<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>
<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. Downcasting means
casting from a base class to a derived class. Crosscasting means casting
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. Old-style casts are sorely lacking in type safety, suffer
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.</p>
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. The <b>polymorphic_cast</b> template performs a <b>dynamic_cast</b>,
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. It must also be used for crosscasts. It does an assert(
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 (ODR) if NDEBUG is inconsistently
defined across translation units. [See ISO Std 3.2]</p>
defined across translation units.&nbsp; [See ISO Std 3.2]</p>
<p>The C++ built-in <b>dynamic_cast</b> must be used to cast references rather
than pointers. It is also the only cast that can be used to check whether
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>
@@ -137,7 +132,7 @@ Abrahams</a>.<b><br>
numeric_cast</b> was contributed by <a href="../../people/kevlin_henney.htm">Kevlin
Henney</a>.</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
<p>Revised&nbsp; <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
-->06 January, 2001<!--webbot bot="Timestamp" endspan i-checksum="38320"
--></p>
<p>© Copyright boost.org 1999. Permission to copy, use, modify, sell and
+4 -5
View File
@@ -9,14 +9,13 @@
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 20 Jan 01 removed use of <limits> for portability to raw GCC (David Abrahams)
// 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 <cfloat> // for DBL_MAX (Peter Schmid)
#include <limits>
#include <boost/cast.hpp>
# if SCHAR_MAX == LONG_MAX
@@ -96,8 +95,8 @@ int main( int argc, char * argv[] )
// tests which should succeed
long small_value = 1;
long small_negative_value = -1;
long large_value = LONG_MAX;
long large_negative_value = LONG_MIN;
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
@@ -143,7 +142,7 @@ int main( int argc, char * argv[] )
if ( !caught_exception ) ++err_count;
caught_exception = false;
try { numeric_cast<int>( DBL_MAX ); }
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;
+66 -103
View File
@@ -9,17 +9,6 @@
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 02 Apr 01 Removed BOOST_NO_LIMITS workarounds and included
// <boost/limits.hpp> instead (the workaround did not
// actually compile when BOOST_NO_LIMITS was defined in
// any case, so we loose nothing). (John Maddock)
// 21 Jan 01 Undid a bug I introduced yesterday. numeric_cast<> never
// worked with stock GCC; trying to get it to do that broke
// vc-stlport.
// 20 Jan 01 Moved BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS to config.hpp.
// Removed unused BOOST_EXPLICIT_TARGET macro. Moved
// boost::detail::type to boost/type.hpp. Made it compile with
// stock gcc again (Dave Abrahams)
// 29 Nov 00 Remove nested namespace cast, cleanup spacing before Formal
// Review (Beman Dawes)
// 19 Oct 00 Fix numeric_cast for floating-point types (Dave Abrahams)
@@ -45,10 +34,8 @@
# include <boost/config.hpp>
# include <cassert>
# include <typeinfo>
# include <boost/type.hpp>
# include <boost/limits.hpp>
# include <boost/detail/select_type.hpp>
# include <typeinfo>
# include <limits>
// It has been demonstrated numerous times that MSVC 6.0 fails silently at link
// time if you use a template function which has template parameters that don't
@@ -56,13 +43,20 @@
//
// TODO: Add this to config.hpp?
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200 // 1200 = VC6
# define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::type<Target>* = 0
# define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::detail::type_wrapper<Target>* = 0
# define BOOST_EXPLICIT_TARGET ,::boost::detail::type_wrapper<Target>*
# else
# define BOOST_EXPLICIT_DEFAULT_TARGET
# define BOOST_EXPLICIT_TARGET
# endif
namespace boost
{
namespace detail
{
template <class T> struct type_wrapper {};
}
// See the documentation for descriptions of how to choose between
// static_cast<>, dynamic_cast<>, polymorphic_cast<> and polymorphic_downcast<>
@@ -122,81 +116,69 @@ namespace boost
// numeric_cast ------------------------------------------------------------//
#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_SGI_CPP_LIMITS)
// Move to config.hpp?
#if defined(_RWSTD_VER) || (defined(__SGI_STL_PORT) && __SGI_STL_PORT <= 0x400 && __STL_STATIC_CONST_INIT_BUG)
// STLPort 4.0 doesn't define the static constants in numeric_limits<> so that they
// can be used at compile time if the compiler bug indicated by
// __STL_STATIC_CONST_INIT_BUG is present.
// Rogue wave STL (C++ Builder) also has broken numeric_limits
// with default template defining members out of line.
# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
#endif
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
namespace detail
{
template <class T>
struct signed_numeric_limits : std::numeric_limits<T>
{
static inline T min()
template <bool is_signed> struct numeric_min_select;
template<>
struct numeric_min_select<true>
{
template <class T>
struct limits : std::numeric_limits<T>
{
return std::numeric_limits<T>::min() >= 0
static inline T min()
# ifndef __GNUC__ // bug workaround courtesy Jens Maurer
{
return std::numeric_limits<T>::min() >= 0
// unary minus causes integral promotion, thus the static_cast<>
? static_cast<T>(-std::numeric_limits<T>::max())
: std::numeric_limits<T>::min();
};
}
# else
;
# endif
};
};
# ifdef __GNUC__ // bug workaround courtesy Jens Maurer
template<> template<class T>
inline T numeric_min_select<true>::limits<T>::min()
{
return std::numeric_limits<T>::min() >= 0
// unary minus causes integral promotion, thus the static_cast<>
? static_cast<T>(-std::numeric_limits<T>::max())
: std::numeric_limits<T>::min();
}
# endif
template<>
struct numeric_min_select<false>
{
template <class T>
struct limits : std::numeric_limits<T> {};
};
// Move to namespace boost in utility.hpp?
template <class T, bool specialized>
struct fixed_numeric_limits_base
: public if_true< std::numeric_limits<T>::is_signed >
::template then< signed_numeric_limits<T>,
std::numeric_limits<T>
>::type
{};
// Move to namespace boost in utility.hpp?
template <class T>
struct fixed_numeric_limits
: fixed_numeric_limits_base<T,(std::numeric_limits<T>::is_specialized)>
{};
# ifdef BOOST_HAS_LONG_LONG
// cover implementations which supply no specialization for long
// long / unsigned long long. Not intended to be full
// numeric_limits replacements, but good enough for numeric_cast<>
template <>
struct fixed_numeric_limits_base<long long, false>
: public numeric_min_select<
std::numeric_limits<T>::is_signed
>::template limits<T>
{
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
BOOST_STATIC_CONSTANT(bool, is_signed = true);
static long long max()
{
# ifdef LONGLONG_MAX
return LONGLONG_MAX;
# else
return 9223372036854775807LL; // hope this is portable
# endif
}
static long long min()
{
# ifdef LONGLONG_MIN
return LONGLONG_MIN;
# else
return -9223372036854775808LL; // hope this is portable
# endif
}
};
template <>
struct fixed_numeric_limits_base<unsigned long long, false>
{
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
BOOST_STATIC_CONSTANT(bool, is_signed = false);
static unsigned long long max()
{
# ifdef ULONGLONG_MAX
return ULONGLONG_MAX;
# else
return 0xffffffffffffffffULL; // hope this is portable
# endif
}
static unsigned long long min() { return 0; }
};
# endif
} // namespace detail
// less_than_type_min -
@@ -260,24 +242,6 @@ namespace boost
template <class X, class Y>
static inline bool check(X x, Y)
{ return x >= 0 && static_cast<X>(static_cast<Y>(x)) != x; }
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200
// MSVC6 can't static_cast unsigned __int64 -> floating types
# define BOOST_UINT64_CAST(src_type) \
static inline bool check(src_type x, unsigned __int64) \
{ \
if (x < 0) return false; \
unsigned __int64 y = static_cast<unsigned __int64>(x); \
bool odd = y & 0x1; \
__int64 div2 = static_cast<__int64>(y >> 1); \
return ((static_cast<src_type>(div2) * 2.0) + odd) != x; \
}
BOOST_UINT64_CAST(long double);
BOOST_UINT64_CAST(double);
BOOST_UINT64_CAST(float);
# undef BOOST_UINT64_CAST
# endif
};
template<>
@@ -307,9 +271,8 @@ namespace boost
# pragma warning(disable : 4018)
# pragma warning(disable : 4146)
#elif defined(__BORLANDC__)
# pragma option push -w-8041
#pragma option push -w-8041
# endif
// Move to namespace boost in utility.hpp?
template <class T>
struct fixed_numeric_limits : public std::numeric_limits<T>
@@ -320,11 +283,10 @@ namespace boost
? T(-std::numeric_limits<T>::max()) : std::numeric_limits<T>::min();
}
};
# if BOOST_MSVC
# pragma warning(pop)
#elif defined(__BORLANDC__)
# pragma option pop
#pragma option pop
# endif
} // namespace detail
@@ -334,10 +296,10 @@ namespace boost
inline Target numeric_cast(Source arg BOOST_EXPLICIT_DEFAULT_TARGET)
{
// typedefs abbreviating respective trait classes
typedef detail::fixed_numeric_limits<Source> arg_traits;
typedef std::numeric_limits<Source> arg_traits;
typedef detail::fixed_numeric_limits<Target> result_traits;
#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_SGI_CPP_LIMITS)
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
// typedefs that act as compile time assertions
// (to be replaced by boost compile time assertions
// as and when they become available and are stable)
@@ -376,6 +338,7 @@ namespace boost
} // numeric_cast
# undef BOOST_EXPLICIT_DEFAULT_TARGET
# undef BOOST_EXPLICIT_TARGET
} // namespace boost
+11 -20
View File
@@ -13,18 +13,11 @@
// where: tested with MSVC 6.0, BCC 5.5, and g++ 2.91
#include <boost/config.hpp>
// Some sstream implementations are broken for the purposes of lexical cast.
# if defined(BOOST_NO_STRINGSTREAM)
# define BOOST_LEXICAL_CAST_USE_STRSTREAM
# ifndef BOOST_NO_STRINGSTREAM
# include <sstream>
# else
# include <strstream>
# endif
#ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
# include <strstream>
#else
# include <sstream>
#endif
#include <typeinfo>
namespace boost
@@ -46,10 +39,10 @@ namespace boost
template<typename Target, typename Source>
Target lexical_cast(Source arg)
{
# ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
std::strstream interpreter; // for out-of-the-box g++ 2.95.2
# else
# ifndef BOOST_NO_STRINGSTREAM
std::stringstream interpreter;
# else
std::strstream interpreter; // for out-of-the-box g++ 2.95.2
# endif
Target result;
@@ -61,16 +54,14 @@ namespace boost
}
}
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
// Copyright Kevlin Henney, 2000. All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
// permissions notice appear in all copies and derivatives, and that no
// charge may be made for the software and its documentation except to cover
// cost of distribution.
//
// This software is provided "as is" without express or implied warranty.
#ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
# undef BOOST_LEXICAL_CAST_USE_STRSTREAM
#endif
#endif
+22 -32
View File
@@ -12,13 +12,13 @@
<a href="../../boost/lexical_cast.hpp">boost/lexical_cast.hpp</a></h1>
<ul>
<li><a href="#motivation">Motivation</a></li>
<li><a href="#examples">Examples</a></li>
<li><a href="#synopsis">Synopsis</a></li>
<li><a href="#lexical_cast"><code>lexical_cast</code></a></li>
<li><a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a></li>
<li><a href="#portability">Portability</a></li>
<li><a href="#future">Future directions</a></li>
<li><a href="#motivation">Motivation</li>
<li></a><a href="#examples">Examples</li>
<li></a><a href="#synopsis">Synopsis</li>
<li></a><a href="#lexical_cast"><code>lexical_cast</code></li>
<li></a><a href="#bad_lexical_cast"><code>bad_lexical_cast</code></li>
<li></a><a href="#portability">Portability</li>
<li></a><a href="#future">Future directions</li>
</ul>
<hr>
@@ -79,13 +79,8 @@ convenience for such conversions. For more involved conversions, such as where
precision or formatting need tighter control than is offered by the default
behavior of <code>lexical_cast</code>, the conventional
<code>stringstream</code> approach is recommended. Where the conversions are
numeric to numeric, <code><a href="cast.htm#numeric_cast">numeric_cast</a></code>
may offer more reasonable behavior than <code>lexical_cast</code>.
<p>
For a good discussion of the options and issues involved in string-based formatting,
including comparison of <code>stringstream</code>, <code>lexical_cast</code>, and
others, see Herb Sutter's article, <a href="http://www.gotw.ca/publications/mill19.htm">
<i>The String Formatters of Manor Farm</i></a>.
numeric to numeric, <code><a href="cast.htm#numeric_cast">numeric_cast</a></code> may offer more reasonable
behavior than <code>lexical_cast</code>.
<p>
<hr>
@@ -132,7 +127,7 @@ void log_errno(int yoko)
<hr>
<h2><a name="synopsis">Synopsis</a></h2>
Library features defined in <a href="../../boost/lexical_cast.hpp"><code>&quot;boost/lexical_cast.hpp&quot;</code></a>:
Library features defined in <a href="lexical_cast.hpp"><code>&quot;boost/lexical_cast.hpp&quot;</code></a>:
<blockquote>
<pre>
@@ -159,8 +154,12 @@ template&lt;typename Target, typename Source&gt;
</blockquote>
Returns the result of streaming <code>arg</code> into a <code>std::stringstream</code> and then
out as a <code>Target</code> object. If the conversion is unsuccessful, a
<a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a> exception is thrown.
out as a <code>Target</code> object. The conversion is parameterized by the current
<a href="#lexical_context"><code>lexical_context</code></a>, if set. If the conversion is
unsuccessful, a <a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a> exception is thrown
if the current <a href="#lexical_context"><code>lexical_context</code></a> is set for throwing or
if there is no current <a href="#lexical_context"><code>lexical_context</code></a> set, otherwise a
<code>Target()</code> is returned.
<p>
The requirements on the argument and result types are:
<ul>
@@ -221,32 +220,23 @@ preference to the standard <code>&lt;sstream&gt;</code> header for out-of-the-bo
<ul>
<li>
Improved string handling, correctly accommodating wide character strings, incompatible
<code>basic_string</code> types, and empty strings.
A mechanism for providing quality-of-service control is needed, e.g. formatting and exception
behavior. In the name of simplicity (and release), the current version strips out an earlier
experimental version.
</li>
<li>
Optimize the use of a stream away for identity conversions.
Wide character and incompatible <code>std::basic_string</code> issues need to be catered for.
</li>
<li>
An <code>interpret_cast</code> that performs a <i>do-something-reasonable</i> conversion between
types. It would, for instance, select between <code>numeric_cast</code> and <code>lexical_cast</code>
based on <code>std::numeric_limits&lt;&gt;::is_specialized</code>. This would be an interesting
project, but there are no concrete plans to pursue this at the moment.
</li>
<li>
It is also worth mentioning future <i>non-directions</i>: anything that involves adding extra
arguments for a conversion operation is not being considered. A custom keyword cast, such as
<code>lexical_cast</code>, is intended to look like a built-in cast operator: built-in cast operators
take only a single operand. Where a higher degree of control is required over conversions, the
standard <code>stringstream</code> offers a more appropriate path. Where non-stream-based conversions
are required, <code>lexical_cast</code> is the wrong tool for the job, and so it won't be special-cased
for such scenarios.
based on <code>std::numeric_limits<>::is_specialized</code>.
</li>
</ul>
<hr>
<div align="right"><small><i>&copy; Copyright Kevlin Henney, 2000, 2002</i></small></div>
<div align="right"><small><i>&copy; Copyright Kevlin Henney, 2000</i></small></div>
</body>
</html>
+3 -13
View File
@@ -2,9 +2,6 @@
// who: developed by Kevlin Henney
// when: November 2000
// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.91
//
// ChangeLog:
// 20 Jan 2001 - Fixed a warning for MSVC (Dave Abrahams)
#ifndef TEST_INCLUDED
#define TEST_INCLUDED
@@ -43,13 +40,6 @@ namespace test // failure exception used to indicate checked test failures
{
}
// std::~string has no exception-specification (could throw anything),
// but we need to be compatible with std::~exception's empty one
// see std::15.4p13 and std::15.4p3
~failure() throw()
{
}
public: // usage
virtual const char * what() const throw()
@@ -114,14 +104,14 @@ namespace test // test utilities
check(lhs != rhs, "expected unequal values: " + description);
}
inline void check_null(const void* ptr, const std::string & description)
inline void check_null(const void * ptr, const std::string & description)
{
check(!ptr, "expected null pointer: " + description);
}
inline void check_non_null(const void* ptr, const std::string & description)
inline void check_non_null(const void * ptr, const std::string & description)
{
check(ptr != 0, "expected non-null pointer: " + description);
check(ptr, "expected non-null pointer: " + description);
}
}