Compare commits

..

1 Commits

Author SHA1 Message Date
nobody 795785cfa7 This commit was manufactured by cvs2svn to create tag
'Version_1_20_2'.

[SVN r9073]
2001-02-10 14:52:07 +00:00
13 changed files with 828 additions and 1078 deletions
+119 -114
View File
@@ -1,90 +1,59 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name="generator" content=
"Microsoft FrontPage 5.0">
<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>
<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="../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Header <a href=
"../../boost/cast.hpp">boost/cast.hpp</a></h1>
<body bgcolor="#FFFFFF" text="#000000">
<h2><a name="Cast Functions">Cast Functions</a></h2>
<p>The header <a href="../../boost/cast.hpp">boost/cast.hpp</a> provides <code>
<a href="#Polymorphic_cast">polymorphic_cast</a> and</code> <a href=
"#Polymorphic_cast"><code>polymorphic_downcast</code></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
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 across an inheritance hierarchy diagram, such
as from one base to the other in a <code>Y</code> 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 poor readability, and are difficult to locate with search
tools.</p>
<p>The C++ built-in <code>static_cast</code> 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 <code>polymorphic_downcast</code> template retains
the efficiency of <code>static_cast</code> for non-debug compilations, but for
debug compilations adds safety via an assert() that a <code>dynamic_cast</code>
succeeds.</p>
<p>The C++ built-in <code>dynamic_cast</code> 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 <code>dynamic_cast</code>, which
works on references, can be used on pointers through the ugly expression
&amp;<code>dynamic_cast&lt;T&amp;&gt;(*p)</code>, which causes undefined
behavior if <code>p</code> is <code>0</code>. The <code>polymorphic_cast</code>
template performs a <code>dynamic_cast</code> on a pointer, and throws an
exception if the <code>dynamic_cast</code> returns 0.</p>
<p>A <code>polymorphic_downcast</code> should be used for
downcasts that you are certain should succeed. Error checking is
only performed in translation units where <code>NDEBUG</code> is
not defined, via
<pre> assert( dynamic_cast&lt;Derived&gt;(x) == x )
</pre> where <code>x</code> 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 <code>polymorphic_downcast</code> will
fail to compile.
<b>Warning:</b> Because <code>polymorphic_downcast</code> uses assert(), it
violates the One Definition Rule (ODR) if NDEBUG is inconsistently
defined across translation units. [See ISO Std 3.2]
</p><p>
For crosscasts, or when the success of a cast can only be known at
runtime, or when efficiency is not important,
<code>polymorphic_cast</code> is preferred. </p>
<p>The C++ built-in <code>dynamic_cast</code> 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.</p>
<h3>polymorphic_cast and polymorphic_downcast synopsis</h3>
<blockquote>
<pre>namespace boost {
<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> function templates designed
to complement the C++ 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>
<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 (ODR) if NDEBUG is inconsistently
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.&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>namespace boost {
template &lt;class Derived, class Base&gt;
inline Derived polymorphic_cast(Base* x);
@@ -96,14 +65,11 @@ 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;
}</pre>
</blockquote>
<h3>polymorphic_downcast example</h3>
<blockquote>
<pre>#include &lt;boost/cast.hpp&gt;
...
class Fruit { public: virtual ~Fruit(){}; ... };
class Banana : public Fruit { ... };
@@ -111,30 +77,69 @@ 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>
...</pre>
</blockquote>
<h3><a name="numeric_cast">numeric_cast</a></h3>
<p>A <b>static_cast</b> or implicit conversion will not
detect failure to preserve range for numeric casts. The <b>numeric_cast</b> function
templates 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 [ISO Std 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>namespace boost {
<h3>History</h3>
class bad_numeric_cast : public std::bad_cast {...};
<p><code>polymorphic_cast</code> was suggested by Bjarne Stroustrup in "The C++
Programming Language".<br>
<code>polymorphic_downcast</code> was contributed by <a href=
"../../people/dave_abrahams.htm">Dave Abrahams</a>.<code><br>
An old
numeric_cast</code> that was contributed by <a href=
"../../people/kevlin_henney.htm">Kevlin Henney</a> is now superseeded by the <a href="../numeric/conversion/doc/index.html">Boost Numeric Conversion Library</a></p>
<hr>
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)
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
-->June 23, 2005<!--webbot bot="Timestamp" endspan i-checksum="30348"
--></p>
}</pre>
</blockquote>
<h3>numeric_cast example</h3>
<blockquote>
<pre>#include &lt;boost/cast.hpp&gt;
using namespace boost::cast;
<p>&copy; 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.</p>
</body>
</html>
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>
<h3>History</h3>
<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>
<hr>
<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
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>
+76 -14
View File
@@ -1,13 +1,14 @@
// boost utility cast test program -----------------------------------------//
// (C) Copyright Beman Dawes, Dave Abrahams 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)
// (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 Set 04 factored out numeric_cast<> test (Fernando Cacciola)
// 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
@@ -15,12 +16,11 @@
#include <iostream>
#include <climits>
#include <cfloat> // for DBL_MAX (Peter Schmid)
#include <boost/cast.hpp>
# if SCHAR_MAX == LONG_MAX
# error "This test program doesn't work if SCHAR_MAX == LONG_MAX"
# endif
# endif
using namespace boost;
using std::cout;
@@ -28,34 +28,39 @@ 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";
cout << "\nBeginning tests...\n";
// test polymorphic_cast ---------------------------------------------------//
// tests which should succeed
Base * base = new Derived;
Base2 * base2 = 0;
@@ -85,6 +90,63 @@ int main( int argc, char * argv[] )
// 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 = LONG_MAX;
long large_negative_value = 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>( DBL_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;
+260 -25
View File
@@ -1,18 +1,14 @@
// boost cast.hpp header file ----------------------------------------------//
// (C) Copyright Kevlin Henney and Dave Abrahams 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)
// (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/libs/conversion for Documentation.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 23 JUn 05 numeric_cast removed and redirected to the new verion (Fernando Cacciola)
// 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.
@@ -27,14 +23,14 @@
// (Dave Abrahams)
// 30 Jun 00 More MSVC6 wordarounds. See comments below. (Dave Abrahams)
// 28 Jun 00 Removed implicit_cast<>. See comment below. (Beman Dawes)
// 27 Jun 00 More MSVC6 workarounds
// 27 Jun 00 More MSVC6 workarounds
// 15 Jun 00 Add workarounds for MSVC6
// 2 Feb 00 Remove bad_numeric_cast ";" syntax error (Doncho Angelov)
// 26 Jan 00 Add missing throw() to bad_numeric_cast::what(0 (Adam Levar)
// 29 Dec 99 Change using declarations so usages in other namespaces work
// correctly (Dave Abrahams)
// 23 Sep 99 Change polymorphic_downcast assert to also detect M.I. errors
// as suggested Darin Adler and improved by Valentin Bonnard.
// as suggested Darin Adler and improved by Valentin Bonnard.
// 2 Sep 99 Remove controversial asserts, simplify, rename.
// 30 Aug 99 Move to cast.hpp, replace value_cast with numeric_cast,
// place in nested namespace.
@@ -44,18 +40,19 @@
#define BOOST_CAST_HPP
# include <boost/config.hpp>
# include <boost/assert.hpp>
# include <cassert>
# include <typeinfo>
# include <boost/type.hpp>
# include <boost/limits.hpp>
# include <boost/detail/select_type.hpp>
# ifndef BOOST_NO_LIMITS
# include <limits>
# endif
// 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
// appear in the function's argument list.
//
// TODO: Add this to config.hpp?
# if defined(BOOST_MSVC) && BOOST_MSVC < 1300
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200 // 1200 = VC6
# define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::type<Target>* = 0
# else
# define BOOST_EXPLICIT_DEFAULT_TARGET
@@ -69,7 +66,7 @@ namespace boost
// polymorphic_cast --------------------------------------------------------//
// Runtime checked polymorphic downcasts and crosscasts.
// Suggested in The C++ Programming Language, 3rd Ed, Bjarne Stroustrup,
// Suggested in The C++ Programming Language, 3rd Ed, Bjarne Stroustrup,
// section 15.8 exercise 1, page 425.
template <class Target, class Source>
@@ -82,26 +79,264 @@ namespace boost
// polymorphic_downcast ----------------------------------------------------//
// BOOST_ASSERT() checked polymorphic downcast. Crosscasts prohibited.
// assert() checked polymorphic downcast. Crosscasts prohibited.
// WARNING: Because this cast uses BOOST_ASSERT(), it violates
// the One Definition Rule if used in multiple translation units
// where BOOST_DISABLE_ASSERTS, BOOST_ENABLE_ASSERT_HANDLER
// NDEBUG are defined inconsistently.
// WARNING: Because this cast uses assert(), it violates the One Definition
// Rule if NDEBUG is inconsistently defined across translation units.
// Contributed by Dave Abrahams
template <class Target, class Source>
inline Target polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
{
BOOST_ASSERT( dynamic_cast<Target>(x) == x ); // detect logic error
assert( dynamic_cast<Target>(x) == x ); // detect logic error
return static_cast<Target>(x);
}
// implicit_cast -----------------------------------------------------------//
//
// Removed due to uncertain purpose. Use either numeric_cast (see below)
// or static_cast according to the need.
// numeric_cast and related exception --------------------------------------//
// Contributed by Kevlin Henney
// bad_numeric_cast --------------------------------------------------------//
// exception used to indicate runtime numeric_cast failure
class bad_numeric_cast : public std::bad_cast
{
public:
// constructors, destructors and assignment operator defaulted
// function inlined for brevity and consistency with rest of library
virtual const char *what() const throw()
{
return "bad numeric cast: loss of range in numeric_cast";
}
};
// numeric_cast ------------------------------------------------------------//
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
namespace detail
{
template <bool is_signed> struct numeric_min_select;
template<>
struct numeric_min_select<true>
{
template <class T>
struct limits : std::numeric_limits<T>
{
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>
struct fixed_numeric_limits
: public numeric_min_select<
std::numeric_limits<T>::is_signed
>::template limits<T>
{
};
} // namespace detail
// less_than_type_min -
// x_is_signed should be numeric_limits<X>::is_signed
// y_is_signed should be numeric_limits<Y>::is_signed
// y_min should be numeric_limits<Y>::min()
//
// check(x, y_min) returns true iff x < y_min without invoking comparisons
// between signed and unsigned values.
//
// "poor man's partial specialization" is in use here.
template <bool x_is_signed, bool y_is_signed>
struct less_than_type_min
{
template <class X, class Y>
static bool check(X x, Y y_min)
{ return x < y_min; }
};
template <>
struct less_than_type_min<false, true>
{
template <class X, class Y>
static bool check(X, Y)
{ return false; }
};
template <>
struct less_than_type_min<true, false>
{
template <class X, class Y>
static bool check(X x, Y)
{ return x < 0; }
};
// greater_than_type_max -
// same_sign should be:
// numeric_limits<X>::is_signed == numeric_limits<Y>::is_signed
// y_max should be numeric_limits<Y>::max()
//
// check(x, y_max) returns true iff x > y_max without invoking comparisons
// between signed and unsigned values.
//
// "poor man's partial specialization" is in use here.
template <bool same_sign, bool x_is_signed>
struct greater_than_type_max;
template<>
struct greater_than_type_max<true, true>
{
template <class X, class Y>
static inline bool check(X x, Y y_max)
{ return x > y_max; }
};
template <>
struct greater_than_type_max<false, true>
{
// What does the standard say about this? I think it's right, and it
// will work with every compiler I know of.
template <class X, class Y>
static inline bool check(X x, Y)
{ return x >= 0 && static_cast<X>(static_cast<Y>(x)) != x; }
};
template<>
struct greater_than_type_max<true, false>
{
template <class X, class Y>
static inline bool check(X x, Y y_max)
{ return x > y_max; }
};
template <>
struct greater_than_type_max<false, false>
{
// What does the standard say about this? I think it's right, and it
// will work with every compiler I know of.
template <class X, class Y>
static inline bool check(X x, Y)
{ return static_cast<X>(static_cast<Y>(x)) != x; }
};
#else // use #pragma hacks if available
namespace detail
{
# if BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4018)
# pragma warning(disable : 4146)
#elif defined(__BORLANDC__)
# pragma option push -w-8041
# endif
# ifndef BOOST_NO_LIMITS
// Move to namespace boost in utility.hpp?
template <class T>
struct fixed_numeric_limits : public std::numeric_limits<T>
{
static inline T min()
{
return std::numeric_limits<T>::is_signed && std::numeric_limits<T>::min() >= 0
? T(-std::numeric_limits<T>::max()) : std::numeric_limits<T>::min();
}
};
# endif // BOOST_NO_LIMITS
# if BOOST_MSVC
# pragma warning(pop)
#elif defined(__BORLANDC__)
# pragma option pop
# endif
} // namespace detail
#endif
template<typename Target, typename Source>
inline Target numeric_cast(Source arg BOOST_EXPLICIT_DEFAULT_TARGET)
{
#ifndef BOOST_NO_LIMITS
// typedefs abbreviating respective trait classes
typedef std::numeric_limits<Source> arg_traits;
typedef detail::fixed_numeric_limits<Target> result_traits;
#endif
#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)
typedef bool argument_must_be_numeric[arg_traits::is_specialized];
typedef bool result_must_be_numeric[result_traits::is_specialized];
const bool arg_is_signed = arg_traits::is_signed;
const bool result_is_signed = result_traits::is_signed;
const bool same_sign = arg_is_signed == result_is_signed;
if (less_than_type_min<arg_is_signed, result_is_signed>::check(arg, result_traits::min())
|| greater_than_type_max<same_sign, arg_is_signed>::check(arg, result_traits::max())
)
#else // We need to use #pragma hacks if available
# if BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4018)
#elif defined(__BORLANDC__)
#pragma option push -w-8012
# endif
if ((arg < 0 && !result_traits::is_signed) // loss of negative range
|| (arg_traits::is_signed && arg < result_traits::min()) // underflow
|| arg > result_traits::max()) // overflow
# if BOOST_MSVC
# pragma warning(pop)
#elif defined(__BORLANDC__)
#pragma option pop
# endif
#endif
{
throw bad_numeric_cast();
}
return static_cast<Target>(arg);
} // numeric_cast
# undef BOOST_EXPLICIT_DEFAULT_TARGET
} // namespace boost
# include <boost/numeric/conversion/cast.hpp>
#endif // BOOST_CAST_HPP
-29
View File
@@ -1,29 +0,0 @@
// Copyright David Abrahams 2003.
// 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)
#ifndef IMPLICIT_CAST_DWA200356_HPP
# define IMPLICIT_CAST_DWA200356_HPP
# include <boost/mpl/identity.hpp>
namespace boost {
// implementation originally suggested by C. Green in
// http://lists.boost.org/MailArchives/boost/msg00886.php
// The use of identity creates a non-deduced form, so that the
// explicit template argument must be supplied
template <typename T>
inline T implicit_cast (typename mpl::identity<T>::type x) {
return x;
}
// incomplete return type now is here
//template <typename T>
//void implicit_cast (...);
} // namespace boost
#endif // IMPLICIT_CAST_DWA200356_HPP
+36 -221
View File
@@ -1,38 +1,24 @@
// boost lexical_cast.hpp header -------------------------------------------//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_LEXICAL_CAST_INCLUDED
#define BOOST_LEXICAL_CAST_INCLUDED
// Boost lexical_cast.hpp header -------------------------------------------//
//
// See http://www.boost.org for most recent version including documentation.
// See end of this header for rights and permissions.
//
// what: lexical_cast custom keyword cast
// who: contributed by Kevlin Henney,
// enhanced with contributions from Terje Slettebø,
// with additional fixes and suggestions from Gennaro Prota,
// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
// and other Boosters
// when: November 2000, March 2003, June 2005
// who: contributed by Kevlin Henney, with alternative naming, behaviors
// and fixes contributed by Dave Abrahams, Daryle Walker and other
// Boosters on the list
// when: November 2000
// where: tested with MSVC 6.0, BCC 5.5, and g++ 2.91
#include <cstddef>
#include <string>
#include <typeinfo>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_pointer.hpp>
#ifdef BOOST_NO_STRINGSTREAM
#include <strstream>
#else
#include <sstream>
#endif
#if defined(BOOST_NO_STRINGSTREAM) || \
defined(BOOST_NO_STD_WSTRING) || \
defined(BOOST_NO_STD_LOCALE)
#define DISABLE_WIDE_CHAR_SUPPORT
#endif
# ifndef BOOST_NO_STRINGSTREAM
# include <sstream>
# else
# include <strstream>
# endif
#include <typeinfo>
namespace boost
{
@@ -40,213 +26,42 @@ namespace boost
class bad_lexical_cast : public std::bad_cast
{
public:
bad_lexical_cast() :
source(&typeid(void)), target(&typeid(void))
{
}
bad_lexical_cast(
const std::type_info &source_type,
const std::type_info &target_type) :
source(&source_type), target(&target_type)
{
}
const std::type_info &source_type() const
{
return *source;
}
const std::type_info &target_type() const
{
return *target;
}
virtual const char *what() const throw()
// constructors, destructors, and assignment operator defaulted
// function inlined for brevity and consistency with rest of library
virtual const char * what() const throw()
{
return "bad lexical cast: "
"source type value could not be interpreted as target";
}
virtual ~bad_lexical_cast() throw()
{
}
private:
const std::type_info *source;
const std::type_info *target;
};
namespace detail // selectors for choosing stream character type
{
template<typename Type>
struct stream_char
{
typedef char type;
};
#ifndef DISABLE_WIDE_CHAR_SUPPORT
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
template<>
struct stream_char<wchar_t>
{
typedef wchar_t type;
};
#endif
template<>
struct stream_char<wchar_t *>
{
typedef wchar_t type;
};
template<>
struct stream_char<const wchar_t *>
{
typedef wchar_t type;
};
template<>
struct stream_char<std::wstring>
{
typedef wchar_t type;
};
#endif
template<typename TargetChar, typename SourceChar>
struct widest_char
{
typedef TargetChar type;
};
template<>
struct widest_char<char, wchar_t>
{
typedef wchar_t type;
};
}
namespace detail // stream wrapper for handling lexical conversions
{
template<typename Target, typename Source>
class lexical_stream
{
private:
typedef typename widest_char<
typename stream_char<Target>::type,
typename stream_char<Source>::type>::type char_type;
public:
lexical_stream()
{
stream.unsetf(std::ios::skipws);
if(std::numeric_limits<Target>::is_specialized)
stream.precision(std::numeric_limits<Target>::digits10 + 1);
else if(std::numeric_limits<Source>::is_specialized)
stream.precision(std::numeric_limits<Source>::digits10 + 1);
}
~lexical_stream()
{
#if defined(BOOST_NO_STRINGSTREAM)
stream.freeze(false);
#endif
}
bool operator<<(const Source &input)
{
return !(stream << input).fail();
}
template<typename InputStreamable>
bool operator>>(InputStreamable &output)
{
return !is_pointer<InputStreamable>::value &&
stream >> output &&
stream.get() ==
#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
// GCC 2.9x lacks std::char_traits<>::eof().
// We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
// configurations, which do provide std::char_traits<>::eof().
EOF;
#else
std::char_traits<char_type>::eof();
#endif
}
bool operator>>(std::string &output)
{
#if defined(BOOST_NO_STRINGSTREAM)
stream << '\0';
#endif
output = stream.str();
return true;
}
#ifndef DISABLE_WIDE_CHAR_SUPPORT
bool operator>>(std::wstring &output)
{
output = stream.str();
return true;
}
#endif
private:
#if defined(BOOST_NO_STRINGSTREAM)
std::strstream stream;
#elif defined(BOOST_NO_STD_LOCALE)
std::stringstream stream;
#else
std::basic_stringstream<char_type> stream;
#endif
};
}
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// call-by-const reference version
namespace detail
{
template<class T>
struct array_to_pointer_decay
{
typedef T type;
};
template<class T, std::size_t N>
struct array_to_pointer_decay<T[N]>
{
typedef const T * type;
};
}
template<typename Target, typename Source>
Target lexical_cast(const Source &arg)
{
typedef typename detail::array_to_pointer_decay<Source>::type NewSource;
detail::lexical_stream<Target, NewSource> interpreter;
Target result;
if(!(interpreter << arg && interpreter >> result))
throw_exception(bad_lexical_cast(typeid(NewSource), typeid(Target)));
return result;
}
#else
// call-by-value fallback version (deprecated)
template<typename Target, typename Source>
Target lexical_cast(Source arg)
{
detail::lexical_stream<Target, Source> interpreter;
# ifndef BOOST_NO_STRINGSTREAM
std::stringstream interpreter;
# else
std::strstream interpreter; // for out-of-the-box g++ 2.95.2
# endif
Target result;
if(!(interpreter << arg && interpreter >> result))
throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
if(!(interpreter << arg) || !(interpreter >> result) ||
!(interpreter >> std::ws).eof())
throw bad_lexical_cast();
return result;
}
#endif
}
// Copyright Kevlin Henney, 2000-2005. All rights reserved.
// Copyright Kevlin Henney, 2000. All rights reserved.
//
// 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)
// 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, 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.
#undef DISABLE_WIDE_CHAR_SUPPORT
#endif
+6 -5
View File
@@ -3,14 +3,14 @@
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Boost Conversion Library</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img border="0" src="../../boost.png" align="center" width="277" height="86">Boost
<h1><img border="0" src="../../c++boost.gif" align="center" width="277" height="86">Boost
Conversion Library</h1>
<p>The Conversion Library improves program safety and clarity by performing
@@ -22,7 +22,8 @@ supplied by several headers:</p>
<ul>
<li>The <a href="cast.htm">boost/cast</a> header provides <b>polymorphic_cast&lt;&gt;</b>
and <b>polymorphic_downcast&lt;&gt;</b> to perform safe casting between
polymorphic types.<br>
polymorphic types, and <b> numeric_cast</b><i>&lt;&gt;</i> to perform safe casting
between numeric types.<br>
</li>
<li>The <a href="lexical_cast.htm">boost/lexical_cast</a> header provides <b>lexical_cast&lt;&gt;</b>
general literal text conversions, such as an <code>int</code> represented as
@@ -30,9 +31,9 @@ supplied by several headers:</p>
</ul>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED"
S-Format="%d %B, %Y" startspan -->June 23, 2005<!--webbot bot="Timestamp" endspan i-checksum="30348" -->
S-Format="%d %B, %Y" startspan -->06 January, 2001<!--webbot bot="Timestamp" endspan i-checksum="38320" -->
</p>
</body>
</html>
</html>
+203 -195
View File
@@ -1,95 +1,95 @@
<!-- saved from url=(0022)http://internet.e-mail -->
<!doctype html public "-//W3C//DTD HTML Transitional 4.0//EN">
<html>
<head>
<title>lexical_cast</title>
<meta name="author" content="Kevlin Henney, mailto:kevlin@curbralan.com">
<meta name="generator" content="Microsoft FrontPage 5.0">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="center" width="277" height="86">Header
<a href="../../boost/lexical_cast.hpp">boost/lexical_cast.hpp</a></h1>
<ul type="square">
<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="#changes">Changes</a></li>
</ul>
<hr>
<h2><a name="motivation">Motivation</a></h2>
Sometimes a value must be converted to a literal text form, such as an <code>int</code>
represented as a <code>string</code>, or vice-versa, when a <code>string</code>
is interpreted as an <code>int</code>. Such examples are common when converting
between data types internal to a program and representation external to a
program, such as windows and configuration files.
<p>
The standard C and C++ libraries offer a number of facilities for performing
such conversions. However, they vary with their ease of use, extensibility, and
safety.
<p>
For instance, there are a number of limitations with the family of standard C
functions typified by <code>atoi</code>:
<ul type="square">
<li>
Conversion is supported in one direction only: from text to internal data type.
Converting the other way using the C library requires either the inconvenience
and compromised safety of the <code>sprintf</code> function, or the loss of
portability associated with non-standard functions such as <code>itoa</code>.
</li>
<li>
The range of types supported is only a subset of the built-in numeric types,
namely <code>int</code>, <code>long</code>, and <code>double</code>.
</li>
<li>
The range of types cannot be extended in a uniform manner. For instance,
conversion from string representation to <code>complex</code> or <code>rational</code>.
</li>
</ul>
The standard C functions typified by <code>strtol</code> have the same basic
limitations, but offer finer control over the conversion process. However, for
the common case such control is often either not required or not used. The <code>scanf</code>
family of functions offer even greater control, but also lack safety and ease
of use.
<p>
The standard C++ library offers <code>stringstream</code> for the kind of
in-core formatting being discussed. It offers a great deal of control over the
formatting and conversion of I/O to and from arbitrary types through text.
However, for simple conversions direct use of <code>stringstream</code> can be
either clumsy (with the introduction of extra local variables and the loss of
infix-expression convenience) or obscure (where <code>stringstream</code>
objects are created as temporary objects in an expression). Facets provide a
comprehensive concept and facility for controlling textual representation, but
their perceived complexity and high entry level requires an extreme degree of
involvement for simple conversions, and excludes all but a few programmers.
<p>
The <code>lexical_cast</code> function template offers a convenient and
consistent form for supporting common conversions to and from arbitrary types
when they are represented as text. The simplification it offers is in
expression-level 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="../numeric/conversion/doc/numeric_cast.html">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>.
<p>
<hr>
<h2><a name="examples">Examples</a></h2>
The following example treats command line arguments as a sequence of numeric
data: <blockquote>
<pre>int main(int argc, char * argv[])
<head>
<title>lexical_cast</title>
<meta name="author" content="Kevlin Henney, mailto:kevlin@curbralan.com">
<meta name="generator" content="Microsoft FrontPage 4.0">
</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/lexical_cast.hpp">boost/lexical_cast.hpp</a></h1>
<ul>
<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>
<h2><a name="motivation">Motivation</a></h2>
Sometimes a value must be converted to a literal text form, such as an
<code>int</code> represented as a <code>string</code>, or vice-versa, when
a <code>string</code> is interpreted as an <code>int</code>. Such examples
are common when converting between data types internal to a program and
representation external to a program, such as windows and configuration files.
<p>
The standard C and C++ libraries offer a number of facilities for performing
such conversions. However, they vary with their ease of use, extensibility,
and safety.
<p>
For instance, there are a number of limitations with the family of standard C
functions typified by <code>atoi</code>:
<ul>
<li>
Conversion is supported in one direction only: from text to
internal data type. Converting the other way using the C library
requires either the inconvenience and compromised safety of the
<code>sprintf</code> function, or the loss of portability associated
with non-standard functions such as <code>itoa</code>.
</li>
<li>
The range of types supported is only a subset of the built-in numeric
types, namely <code>int</code>, <code>long</code>,
and <code>double</code>.
</li>
<li>
The range of types cannot be extended in a uniform manner. For
instance, conversion from string representation to
<code>complex</code> or <code>rational</code>.
</li>
</ul>
The standard C functions typified by <code>strtol</code> have the same basic
limitations, but offer finer control over the conversion process. However, for
the common case such control is often either not required or not used. The
<code>scanf</code> family of functions offer even greater control, but also
lack safety and ease of use.
<p>
The standard C++ library offers <code>stringstream</code> for the kind of
in-core formatting being discussed. It offers a great deal of control over the
formatting and conversion of I/O to and from arbitrary types through text.
However, for simple conversions direct use of <code>stringstream</code> can be
either clumsy (with the introduction of extra local variables and the loss of
infix-expression convenience) or obscure (where <code>stringstream</code>
objects are created as temporary objects in an expression). Facets provide a
comprehensive concept and facility for controlling textual representation, but
their relatively high entry level requires an extreme degree of involvement
for simple conversions.
<p>
The <code>lexical_cast</code> template function offers a convenient and consistent
form for supporting common conversions to and from arbitrary types when they are
represented as text. The simplification it offers is in expression-level
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>
<hr>
<h2><a name="examples">Examples</a></h2>
The following example treats command line arguments as a sequence of numeric data:
<blockquote>
<pre>
int main(int argc, char * argv[])
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
@@ -110,125 +110,133 @@
...
}
</pre>
</blockquote>The following example uses numeric data in a string expression: <blockquote>
<pre>void log_message(const std::string &amp;);
</blockquote>
The following example uses numeric data in a string expression:
<blockquote>
<pre>
void log_message(const std::string &amp;);
void log_errno(int yoko)
{
log_message(&quot;Error &quot; + boost::lexical_cast&lt;std::string&gt;(yoko) + &quot;: &quot; + strerror(yoko));
}
</pre>
</blockquote>
<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>:
<blockquote>
<pre>namespace boost
</blockquote>
<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>:
<blockquote>
<pre>
namespace boost
{
class <a href="#bad_lexical_cast">bad_lexical_cast</a>;
template&lt;typename Target, typename Source&gt;
Target <a href="#lexical_cast">lexical_cast</a>(const Source&amp; arg);
Target <a href="#lexical_cast">lexical_cast</a>(Source arg);
}
</pre>
</blockquote>Unit test defined in <a href="lexical_cast_test.cpp"><code>&quot;lexical_cast_test.cpp&quot;</code></a>.
<p>
<hr>
<h2><a name="lexical_cast"><code>lexical_cast</code></a></h2>
<blockquote>
<pre>template&lt;typename Target, typename Source&gt;
Target lexical_cast(const Source&amp; arg);
</blockquote>
Test harness defined in <a href="lexical_cast_test.cpp"><code>&quot;lexical_cast_test.cpp&quot;</code></a>.
<p>
<hr>
<h2><a name="lexical_cast"><code>lexical_cast</code></a></h2>
<blockquote>
<pre>
template&lt;typename Target, typename Source&gt;
Target lexical_cast(Source arg);
</pre>
</blockquote>Returns the result of streaming <code>arg</code> into a
standard library string-based stream and then out as a <code>Target</code> object.
Where <code>Target</code> is either <code>std::string</code>
or <code>std::wstring</code>, stream extraction takes the whole content
of the string, including spaces, rather than relying on the default
<code>operator&gt;&gt;</code> behavior.
If the conversion is unsuccessful, a <a href="#bad_lexical_cast">
<code>bad_lexical_cast</code></a> exception is thrown.
<p>
The requirements on the argument and result types are:
<ul type="square">
<li>
<code>Source</code> is <i>OutputStreamable</i>, meaning that an <code>operator&lt;&lt;</code>
is defined that takes a <code>std::ostream</code> or <code>std::wostream</code> object on the
left hand side and an instance of the argument type on the right.
</li>
<li>
<code>Target</code> is <i>InputStreamable</i>, meaning that an <code>operator&gt;&gt;</code>
is defined that takes a <code>std::istream</code> or <code>std::wistream</code> object on the left hand side
and an instance of the result type on the right.
</li>
<li>
Both <code>Source</code> and <code>Target</code> are <i>CopyConstructible</i> [20.1.3].
</li>
<li>
<code>Target</code> is <i>DefaultConstructible</i>, meaning that it is possible
to <i>default-initialize</i> an object of that type [8.5, 20.1.4].
</li>
</ul>
The character type of the underlying stream is assumed to be <code>char</code> unless
either the <code>Source</code> or the <code>Target</code> requires wide-character
streaming, in which case the underlying stream uses <code>wchar_t</code>.
<code>Source</code> types that require wide-character streaming are <code>wchar_t</code>,
<code>wchar_t *</code>, and <code>std::wstring</code>. <code>Target</code> types that
require wide-character streaming are <code>wchar_t</code> and <code>std::wstring</code>.
<p>
Where a higher degree of control is required over conversions, <code>std::stringstream</code>
and <code>std::wstringstream</code> offer a more appropriate path. Where non-stream-based conversions are
required, <code>lexical_cast</code>
is the wrong tool for the job and is not special-cased for such scenarios.
<p>
<hr>
<h2><a name="bad_lexical_cast"><code>bad_lexical_cast</code></a></h2>
<blockquote>
<pre>class bad_lexical_cast : public std::bad_cast
</blockquote>
Returns the result of streaming <code>arg</code> into a <code>std::stringstream</code> and then
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>
<li>
<code>Source</code> is <i>OutputStreamable</i>, meaning that an
<code>operator&lt;&lt;</code> is defined that takes a
<code>std::ostream</code> object on the left hand side and an instance
of the argument type on the right.
</li>
<li>
Both <code>Source</code> and <code>Target</code> are <i>CopyConstructible</i> [20.1.3].
</li>
<li>
<code>Target</code> is <i>InputStreamable</i>, meaning that an
<code>operator&gt;&gt;</code> is defined that takes a
<code>std::istream</code> object on the left hand side and an instance
of the result type on the right.
</li>
<li>
<code>Target</code> is <i>DefaultConstructible</i>, meaning that it is
possible to <i>default-initialize</i> an object of that type [8.5, 20.1.3].
</li>
<li>
<code>Target</code> is <i>Assignable</i> [23.1].
</li>
</ul>
<p>
<hr>
<h2><a name="bad_lexical_cast"><code>bad_lexical_cast</code></a></h2>
<blockquote>
<pre>
class bad_lexical_cast : public std::bad_cast
{
public:
... // <i>same member function interface as</i> std::exception
virtual const char * what() const throw();
};
</pre>
</blockquote>Exception used to indicate runtime <a href="#lexical_cast"><code>lexical_cast</code></a>
failure.
<hr>
<h2><a name="changes">Changes</a></h2>
<h3>June 2005:</h3>
<ul type="square">
<li>Call-by-const reference for the parameters. This requires partial specialization
of class templates, so it doesn't work for MSVC 6, and it uses the original
pass by value there.<br>
</li>
<li>The MSVC 6 support is deprecated, and will be removed in a future Boost
version. </li>
</blockquote>
Exception used to indicate runtime <a href="#lexical_cast"><code>lexical_cast</code></a> failure.
<p>
<hr>
<h2><a name="portability">Portability</a></h2>
To date the code and test harness have been compiled successfully using
Microsoft Visual C++ 6.0, Borland C++ 5.5, and GNU g++ 2.91. Tests have run successfully for
Microsoft Visual C++ 6.0 and Borland C++ 5.5. For g++ streams interpret any integer, rather than
just <code>0</code> and <code>1</code>, as valid for <code>bool</code>; the other tests pass
without problem. The deprecated standard header <code>&lt;strstream&gt;</code> is used in
preference to the standard <code>&lt;sstream&gt;</code> header for out-of-the-box g++ support.
<p>
<hr>
<h2><a name="future">Future directions</a></h2>
<ul>
<li>
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>
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<>::is_specialized</code>.
</li>
</ul>
<h3>Earlier:</h3>
<ul type="square">
<li>The previous version of <code>lexical_cast</code> used the default stream
precision for reading and writing floating-point numbers. For numerics that
have a corresponding specialization of <code>std::numeric_limits</code>, the
current version now chooses a precision to match. <br>
<li>The previous version of <code>lexical_cast</code> did not support conversion
to or from any wide-character-based types. For compilers with full language
and library support for wide characters, <code>lexical_cast</code> now supports
conversions from <code>wchar_t</code>, <code>wchar_t *</code>, and <code>std::wstring</code>
and to <code>wchar_t</code> and <code>std::wstring</code>. <br>
<li>The previous version of <code>lexical_cast</code> assumed that the conventional
stream extractor operators were sufficient for reading values. However, string
I/O is asymmetric, with the result that spaces play the role of I/O separators
rather than string content. The current version fixes this error for <code>std::string</code>
and, where supported, <code>std::wstring</code>: <code>lexical_cast&lt;std::string&gt;("Hello,
World")</code> succeeds instead of failing with a <code>bad_lexical_cast</code>
exception. <br>
<li>The previous version of <code>lexical_cast</code> allowed unsafe and meaningless
conversions to pointers. The current version now throws a <code>bad_lexical_cast</code>
for conversions to pointers: <code>lexical_cast&lt;char *&gt;("Goodbye, World")</code>
now throws an exception instead of causing undefined behavior.
</ul>
<p>
<hr>
<div align="right"><small><i>&copy; Copyright Kevlin Henney, 2000&#150;2005</i></small></div>
</body>
</html>
<hr>
<div align="right"><small><i>&copy; Copyright Kevlin Henney, 2000</i></small></div>
</body>
</html>
+120 -291
View File
@@ -1,320 +1,149 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Terje Slettebø and Kevlin Henney, 2005.
//
// 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).
//
// Note: The unit test no longer compile on MSVC 6, but lexical_cast itself works for it.
// boost lexical_cast_test.cpp program -------------------------------------//
#include <boost/config.hpp>
// See http://www.boost.org for most recent version including documentation.
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
// what: lexical_cast custom keyword cast tests
// who: contributed by Kevlin Henney
// when: October 2000
// where: tested with MSVC 6.0 and BCC 5.5
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
#if defined(BOOST_NO_STRINGSTREAM) || \
defined(BOOST_NO_STD_WSTRING) || \
defined(BOOST_NO_STD_LOCALE)
#define DISABLE_WIDE_CHAR_SUPPORT
#endif
#include "test.hpp"
#include <complex>
#include <iostream>
#include <string>
using namespace boost;
using namespace std;
void test_conversion_to_char();
void test_conversion_to_int();
void test_conversion_to_double();
void test_conversion_to_bool();
void test_conversion_to_string();
void test_conversion_from_to_wchar_t_alias();
void test_conversion_to_pointer();
void test_conversion_from_wchar_t();
void test_conversion_to_wchar_t();
void test_conversion_from_wstring();
void test_conversion_to_wstring();
void test_bad_lexical_cast();
void test_no_whitespace_stripping();
typedef test::test<const char *, void (*)()> test_case;
typedef const test_case * test_case_iterator;
unit_test::test_suite *init_unit_test_suite(int, char *[])
extern const test_case_iterator begin, end;
int main()
{
unit_test_framework::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast unit test");
suite->add(BOOST_TEST_CASE(test_conversion_to_char));
suite->add(BOOST_TEST_CASE(test_conversion_to_int));
suite->add(BOOST_TEST_CASE(test_conversion_to_double));
suite->add(BOOST_TEST_CASE(test_conversion_to_bool));
suite->add(BOOST_TEST_CASE(test_conversion_from_to_wchar_t_alias));
suite->add(BOOST_TEST_CASE(test_conversion_to_pointer));
suite->add(BOOST_TEST_CASE(test_conversion_to_string));
#ifndef DISABLE_WIDE_CHAR_SUPPORT
suite->add(BOOST_TEST_CASE(test_conversion_from_wchar_t));
suite->add(BOOST_TEST_CASE(test_conversion_to_wchar_t));
suite->add(BOOST_TEST_CASE(test_conversion_from_wstring));
suite->add(BOOST_TEST_CASE(test_conversion_to_wstring));
#endif
suite->add(BOOST_TEST_CASE(test_bad_lexical_cast));
suite->add(BOOST_TEST_CASE(test_no_whitespace_stripping));
return suite;
test::tester<test_case_iterator> test_suite(begin, end);
return test_suite() ? EXIT_SUCCESS : EXIT_FAILURE;
}
void test_conversion_to_char()
void test_to_string()
{
BOOST_CHECK_EQUAL('A', lexical_cast<char>('A'));
BOOST_CHECK_EQUAL(' ', lexical_cast<char>(' '));
BOOST_CHECK_EQUAL('1', lexical_cast<char>(1));
BOOST_CHECK_EQUAL('0', lexical_cast<char>(0));
BOOST_CHECK_THROW(lexical_cast<char>(123), bad_lexical_cast);
BOOST_CHECK_EQUAL('1', lexical_cast<char>(1.0));
BOOST_CHECK_EQUAL('1', lexical_cast<char>(true));
BOOST_CHECK_EQUAL('0', lexical_cast<char>(false));
BOOST_CHECK_EQUAL('A', lexical_cast<char>("A"));
BOOST_CHECK_EQUAL(' ', lexical_cast<char>(" "));
BOOST_CHECK_THROW(lexical_cast<char>(""), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<char>("Test"), bad_lexical_cast);
BOOST_CHECK_EQUAL('A', lexical_cast<char>(std::string("A")));
BOOST_CHECK_EQUAL(' ', lexical_cast<char>(std::string(" ")));
BOOST_CHECK_THROW(
lexical_cast<char>(std::string("")), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<char>(std::string("Test")), bad_lexical_cast);
test::check_equal(
lexical_cast<string>(2001), "2001",
"2001 -> \"2001\"");
test::check_equal(
lexical_cast<string>(2001.0), "2001",
"2001.0 ->\"2001\"");
test::check_equal(
lexical_cast<string>(complex<double>(2000,1)), "(2000,1)",
"complex<double>(2000,1) -> \"(2000,1)\"");
}
void test_conversion_to_int()
void test_to_int()
{
BOOST_CHECK_EQUAL(1, lexical_cast<int>('1'));
BOOST_CHECK_EQUAL(0, lexical_cast<int>('0'));
BOOST_CHECK_THROW(lexical_cast<int>('A'), bad_lexical_cast);
BOOST_CHECK_EQUAL(1, lexical_cast<int>(1));
BOOST_CHECK_EQUAL(
(std::numeric_limits<int>::max)(),
lexical_cast<int>((std::numeric_limits<int>::max)()));
BOOST_CHECK_EQUAL(1, lexical_cast<int>(1.0));
BOOST_CHECK_THROW(lexical_cast<int>(1.23), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<int>(1e20), bad_lexical_cast);
BOOST_CHECK_EQUAL(1, lexical_cast<int>(true));
BOOST_CHECK_EQUAL(0, lexical_cast<int>(false));
BOOST_CHECK_EQUAL(123, lexical_cast<int>("123"));
BOOST_CHECK_THROW(
lexical_cast<int>(" 123"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<int>(""), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<int>("Test"), bad_lexical_cast);
BOOST_CHECK_EQUAL(123, lexical_cast<int>("123"));
BOOST_CHECK_EQUAL(123, lexical_cast<int>(std::string("123")));
BOOST_CHECK_THROW(
lexical_cast<int>(std::string(" 123")), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<int>(std::string("")), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<int>(std::string("Test")), bad_lexical_cast);
test::check_equal(
lexical_cast<int>("2001"), 2001,
"\"2001\" -> 2001");
test::check_equal(
lexical_cast<int>(" 2001"), 2001,
"\" 2001\" -> 2001");
test::check_equal(
lexical_cast<int>("2001 "), 2001,
"\"2001 \" -> 2001");
TEST_CHECK_THROW(
lexical_cast<int>("Two thousand and one"),
bad_lexical_cast,
"\"Two thousand and one\"");
TEST_CHECK_THROW(
lexical_cast<int>("2001: A Space Odyssey"),
bad_lexical_cast,
"\"2001: A Space Odyssey\"");
TEST_CHECK_THROW(
lexical_cast<int>(200.1),
bad_lexical_cast,
"200.1");
TEST_CHECK_THROW(
lexical_cast<int>("200e1"),
bad_lexical_cast,
"\"200e1\"");
}
void test_conversion_to_double()
void test_to_char()
{
BOOST_CHECK_CLOSE(1.0, lexical_cast<double>('1'), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_THROW(lexical_cast<double>('A'), bad_lexical_cast);
BOOST_CHECK_CLOSE(1.0, lexical_cast<double>(1), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE(1.23, lexical_cast<double>(1.23), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE(1.234567890, 1.234567890, std::numeric_limits<double>::epsilon());
BOOST_CHECK_CLOSE(1.0, lexical_cast<double>(true), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE(0.0, lexical_cast<double>(false), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE(1.23, lexical_cast<double>("1.23"), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_THROW(lexical_cast<double>(""), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<double>("Test"), bad_lexical_cast);
BOOST_CHECK_CLOSE(1.23, lexical_cast<double>(std::string("1.23")), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_THROW(
lexical_cast<double>(std::string("")), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<double>(std::string("Test")), bad_lexical_cast);
test::check_equal(
lexical_cast<char>("2"), '2',
"\"2\" -> '2'");
test::check_equal(
lexical_cast<char>(" 2"), '2',
"\" 2\" -> '2'");
test::check_equal(
lexical_cast<char>("2 "), '2',
"\"2 \" -> '2'");
test::check_equal(
lexical_cast<char>(2), '2',
"2 -> '2'");
TEST_CHECK_THROW(
lexical_cast<char>("2001"),
bad_lexical_cast,
"\"2001\"");
TEST_CHECK_THROW(
lexical_cast<char>(2001),
bad_lexical_cast,
"2001");
}
void test_conversion_to_bool()
void test_to_double()
{
BOOST_CHECK_EQUAL(true, lexical_cast<bool>('1'));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>('0'));
BOOST_CHECK_THROW(lexical_cast<bool>('A'), bad_lexical_cast);
BOOST_CHECK_EQUAL(true, lexical_cast<bool>(1));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>(0));
BOOST_CHECK_THROW(lexical_cast<bool>(123), bad_lexical_cast);
BOOST_CHECK_EQUAL(true, lexical_cast<bool>(1.0));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>(0.0));
BOOST_CHECK_EQUAL(true, lexical_cast<bool>(true));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>(false));
BOOST_CHECK_EQUAL(true, lexical_cast<bool>("1"));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>("0"));
BOOST_CHECK_THROW(lexical_cast<bool>(""), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<bool>("Test"), bad_lexical_cast);
BOOST_CHECK_EQUAL(true, lexical_cast<bool>("1"));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>("0"));
BOOST_CHECK_EQUAL(true, lexical_cast<bool>(std::string("1")));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>(std::string("0")));
BOOST_CHECK_THROW(
lexical_cast<bool>(std::string("")), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<bool>(std::string("Test")), bad_lexical_cast);
test::check_equal(
lexical_cast<double>("1e6"), 1e6,
"\"1e6\" -> 1e6");
test::check_equal(
lexical_cast<double>("1e-2"), 1e-2,
"\"1e-2\" -> 1e-2");
}
void test_conversion_to_string()
void test_to_bool()
{
BOOST_CHECK_EQUAL("A", lexical_cast<std::string>('A'));
BOOST_CHECK_EQUAL(" ", lexical_cast<std::string>(' '));
BOOST_CHECK_EQUAL("123", lexical_cast<std::string>(123));
BOOST_CHECK_EQUAL("1.23", lexical_cast<std::string>(1.23));
BOOST_CHECK_EQUAL("1.111111111", lexical_cast<std::string>(1.111111111));
BOOST_CHECK_EQUAL("1", lexical_cast<std::string>(true));
BOOST_CHECK_EQUAL("0", lexical_cast<std::string>(false));
BOOST_CHECK_EQUAL("Test", lexical_cast<std::string>("Test"));
BOOST_CHECK_EQUAL(" ", lexical_cast<std::string>(" "));
BOOST_CHECK_EQUAL("", lexical_cast<std::string>(""));
BOOST_CHECK_EQUAL("Test", lexical_cast<std::string>(std::string("Test")));
BOOST_CHECK_EQUAL(" ", lexical_cast<std::string>(std::string(" ")));
BOOST_CHECK_EQUAL("", lexical_cast<std::string>(std::string("")));
test::check_equal(
lexical_cast<bool>(1), true,
"1 -> true");
test::check_equal(
lexical_cast<bool>('0'), false,
"'0' -> false");
TEST_CHECK_THROW(
lexical_cast<bool>(2001),
bad_lexical_cast,
"2001");
TEST_CHECK_THROW(
lexical_cast<bool>(2),
bad_lexical_cast,
"2");
TEST_CHECK_THROW(
lexical_cast<bool>("true thousand and one"),
bad_lexical_cast,
"\"true thousand and one\"");
}
void test_conversion_from_to_wchar_t_alias()
const test_case test_cases[] =
{
BOOST_CHECK_EQUAL(123u, lexical_cast<unsigned short>("123"));
BOOST_CHECK_EQUAL(123u, lexical_cast<unsigned int>("123"));
BOOST_CHECK_EQUAL(123u, lexical_cast<unsigned long>("123"));
BOOST_CHECK_EQUAL(std::string("123"),
lexical_cast<std::string>(static_cast<unsigned short>(123)));
BOOST_CHECK_EQUAL(std::string("123"), lexical_cast<std::string>(123u));
BOOST_CHECK_EQUAL(std::string("123"), lexical_cast<std::string>(123ul));
}
{ "lexical_cast<std::string>", test_to_string },
{ "lexical_cast<int>", test_to_int },
{ "lexical_cast<char>", test_to_char },
{ "lexical_cast<double>", test_to_double },
{ "lexical_cast<bool>", test_to_bool }
};
void test_conversion_to_pointer()
{
BOOST_CHECK_THROW(lexical_cast<char *>("Test"), bad_lexical_cast);
#ifndef DISABLE_WIDE_CHAR_SUPPORT
BOOST_CHECK_THROW(lexical_cast<wchar_t *>("Test"), bad_lexical_cast);
#endif
}
const test_case_iterator begin = test_cases;
const test_case_iterator end =
test_cases + (sizeof test_cases / sizeof *test_cases);
void test_conversion_from_wchar_t()
{
#ifndef DISABLE_WIDE_CHAR_SUPPORT
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_CHECK_EQUAL(1, lexical_cast<int>(L'1'));
BOOST_CHECK_THROW(lexical_cast<int>(L'A'), bad_lexical_cast);
#endif
BOOST_CHECK_EQUAL(123, lexical_cast<int>(L"123"));
BOOST_CHECK_THROW(lexical_cast<int>(L""), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<int>(L"Test"), bad_lexical_cast);
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_CHECK_EQUAL(1.0, lexical_cast<double>(L'1'));
BOOST_CHECK_THROW(lexical_cast<double>(L'A'), bad_lexical_cast);
#endif
BOOST_CHECK_EQUAL(1.23, lexical_cast<double>(L"1.23"));
BOOST_CHECK_THROW(lexical_cast<double>(L""), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<double>(L"Test"), bad_lexical_cast);
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_CHECK_EQUAL(true, lexical_cast<bool>(L'1'));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>(L'0'));
BOOST_CHECK_THROW(lexical_cast<bool>(L'A'), bad_lexical_cast);
#endif
BOOST_CHECK_EQUAL(true, lexical_cast<bool>(L"1"));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>(L"0"));
BOOST_CHECK_THROW(lexical_cast<bool>(L""), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<bool>(L"Test"), bad_lexical_cast);
#endif
}
void test_conversion_to_wchar_t()
{
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>(1));
BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>(0));
BOOST_CHECK_THROW(lexical_cast<wchar_t>(123), bad_lexical_cast);
BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>(1.0));
BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>(0.0));
BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>(true));
BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>(false));
BOOST_CHECK_EQUAL(L'A', lexical_cast<wchar_t>(L'A'));
BOOST_CHECK_EQUAL(L' ', lexical_cast<wchar_t>(L' '));
BOOST_CHECK_EQUAL(L'A', lexical_cast<wchar_t>(L"A"));
BOOST_CHECK_EQUAL(L' ', lexical_cast<wchar_t>(L" "));
BOOST_CHECK_THROW(lexical_cast<wchar_t>(L""), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<wchar_t>(L"Test"), bad_lexical_cast);
BOOST_CHECK_EQUAL(L'A', lexical_cast<wchar_t>(std::wstring(L"A")));
BOOST_CHECK_EQUAL(L' ', lexical_cast<wchar_t>(std::wstring(L" ")));
BOOST_CHECK_THROW(
lexical_cast<wchar_t>(std::wstring(L"")), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<wchar_t>(std::wstring(L"Test")), bad_lexical_cast);
#endif
}
void test_conversion_from_wstring()
{
#ifndef DISABLE_WIDE_CHAR_SUPPORT
BOOST_CHECK_EQUAL(123, lexical_cast<int>(std::wstring(L"123")));
BOOST_CHECK_THROW(
lexical_cast<int>(std::wstring(L"")), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<int>(std::wstring(L"Test")), bad_lexical_cast);
BOOST_CHECK_EQUAL(true, lexical_cast<bool>(std::wstring(L"1")));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>(std::wstring(L"0")));
BOOST_CHECK_THROW(
lexical_cast<bool>(std::wstring(L"")), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<bool>(std::wstring(L"Test")), bad_lexical_cast);
#endif
}
void test_conversion_to_wstring()
{
#ifndef DISABLE_WIDE_CHAR_SUPPORT
BOOST_CHECK(L"123" == lexical_cast<std::wstring>(123));
BOOST_CHECK(L"1.23" == lexical_cast<std::wstring>(1.23));
BOOST_CHECK(L"1.111111111" == lexical_cast<std::wstring>(1.111111111));
BOOST_CHECK(L"1" == lexical_cast<std::wstring>(true));
BOOST_CHECK(L"0" == lexical_cast<std::wstring>(false));
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_CHECK(L"A" == lexical_cast<std::wstring>(L'A'));
BOOST_CHECK(L" " == lexical_cast<std::wstring>(L' '));
#endif
BOOST_CHECK(L"Test" == lexical_cast<std::wstring>(L"Test"));
BOOST_CHECK(L" " == lexical_cast<std::wstring>(L" "));
BOOST_CHECK(L"" == lexical_cast<std::wstring>(L""));
BOOST_CHECK(L"Test" == lexical_cast<std::wstring>(std::wstring(L"Test")));
BOOST_CHECK(L" " == lexical_cast<std::wstring>(std::wstring(L" ")));
BOOST_CHECK(L"" == lexical_cast<std::wstring>(std::wstring(L"")));
#endif
}
void test_bad_lexical_cast()
{
try
{
lexical_cast<int>(std::string("Test"));
BOOST_CHECK(false); // Exception expected
}
catch(const bad_lexical_cast &e)
{
BOOST_CHECK(e.source_type() == typeid(std::string));
BOOST_CHECK(e.target_type() == typeid(int));
}
}
void test_no_whitespace_stripping()
{
BOOST_CHECK_THROW(lexical_cast<int>(" 123"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<int>("123 "), bad_lexical_cast);
}
// 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, 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.
-100
View File
@@ -1,100 +0,0 @@
// boost utility cast test program -----------------------------------------//
// (C) Copyright Beman Dawes, Dave Abrahams 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)
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 28 Set 04 factored out numeric_cast<> test (Fernando Cacciola)
// 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 <boost/cast.hpp>
#include "boost/test/minimal.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;
int test_main( int argc, char * argv[] )
{
# ifdef NDEBUG
cout << "NDEBUG is defined\n";
# else
cout << "NDEBUG is not defined\n";
# endif
cout << "\nBeginning tests...\n";
// test implicit_cast and numeric_cast -------------------------------------//
// tests which should succeed
long small_value = 1;
long small_negative_value = -1;
long large_value = LONG_MAX;
long large_negative_value = LONG_MIN;
signed char c = 0;
c = large_value; // see if compiler generates warning
c = numeric_cast<signed char>( small_value );
BOOST_CHECK( c == 1 );
c = 0;
c = numeric_cast<signed char>( small_value );
BOOST_CHECK( c == 1 );
c = 0;
c = numeric_cast<signed char>( small_negative_value );
BOOST_CHECK( c == -1 );
// These tests courtesy of Joe R NWP Swatosh<joe.r.swatosh@usace.army.mil>
BOOST_CHECK( 0.0f == numeric_cast<float>( 0.0 ) );
BOOST_CHECK( 0.0 == numeric_cast<double>( 0.0 ) );
// tests which should result in errors being detected
bool 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; }
BOOST_CHECK ( caught_exception );
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; }
BOOST_CHECK ( caught_exception );
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; }
BOOST_CHECK ( caught_exception );
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; }
BOOST_CHECK ( caught_exception );
caught_exception = false;
try { numeric_cast<int>( DBL_MAX ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #5\n"; caught_exception = true; }
BOOST_CHECK ( caught_exception );
return 0 ;
}
+8 -4
View File
@@ -44,7 +44,7 @@ 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
// but we need to be compatible with std::~exception's empty one
// see std::15.4p13 and std::15.4p3
~failure() throw()
{
@@ -303,6 +303,10 @@ namespace test // tester is the driver class for a sequence of tests
// Copyright Kevlin Henney, 2000. All rights reserved.
//
// 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)
// 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, 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.
-26
View File
@@ -1,26 +0,0 @@
# Signals library
# Copyright (C) 2001-2003 Douglas Gregor
# Permission to copy, use, sell and distribute this software is granted
# provided this copyright notice appears in all copies. Permission to modify
# the code and to distribute modified code is granted provided this copyright
# notice appears in all copies, and a notice that the code was modified is
# included with the copyright notice. This software is provided "as is"
# without express or implied warranty, and with no claim as to its suitability
# for any purpose.
# For more information, see http://www.boost.org/
# bring in rules for testing
import testing ;
test-suite conversion
: [ run implicit_cast.cpp ]
[ compile-fail implicit_cast_fail.cpp ]
[ run ../cast_test.cpp ]
[ run ../numeric_cast_test.cpp ]
[ run ../lexical_cast_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
;
-32
View File
@@ -1,32 +0,0 @@
// Copyright David Abrahams 2003.
// 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)
#include <boost/implicit_cast.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/type.hpp>
using boost::implicit_cast;
using boost::type;
template <class T>
type<T> check_return(T) { return type<T>(); }
struct foo
{
foo(char const*) {}
operator long() const { return 0; }
};
typedef type<long> long_type;
typedef type<foo> foo_type;
int main()
{
type<long> x = check_return(boost::implicit_cast<long>(1));
BOOST_TEST(boost::implicit_cast<long>(1) == 1L);
type<foo> f = check_return(boost::implicit_cast<foo>("hello"));
type<long> z = check_return(boost::implicit_cast<long>(foo("hello")));
return boost::report_errors();
}
-22
View File
@@ -1,22 +0,0 @@
// Copyright David Abrahams 2003.
// 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)
#include <boost/implicit_cast.hpp>
#include <boost/type.hpp>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
using boost::implicit_cast;
struct foo
{
explicit foo(char const*) {}
};
int test_main(int, char*[])
{
foo x = implicit_cast<foo>("foobar");
}