forked from boostorg/conversion
This commit was manufactured by cvs2svn to create tag
'SPIRIT_1_6_4_MINIBOOST'. [SVN r38030]
This commit is contained in:
140
cast.htm
140
cast.htm
@@ -1,140 +0,0 @@
|
|||||||
<!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>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<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
|
|
||||||
&<code>dynamic_cast<T&>(*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<Derived>(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 {
|
|
||||||
|
|
||||||
template <class Derived, class Base>
|
|
||||||
inline Derived polymorphic_cast(Base* x);
|
|
||||||
// Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
|
|
||||||
// Returns: dynamic_cast<Derived>(x)
|
|
||||||
|
|
||||||
template <class Derived, class Base>
|
|
||||||
inline Derived polymorphic_downcast(Base* x);
|
|
||||||
// Effects: assert( dynamic_cast<Derived>(x) == x );
|
|
||||||
// Returns: static_cast<Derived>(x)
|
|
||||||
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<h3>polymorphic_downcast example</h3>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>#include <boost/cast.hpp>
|
|
||||||
...
|
|
||||||
class Fruit { public: virtual ~Fruit(){}; ... };
|
|
||||||
class Banana : public Fruit { ... };
|
|
||||||
...
|
|
||||||
void f( Fruit * fruit ) {
|
|
||||||
// ... logic which leads us to believe it is a Banana
|
|
||||||
Banana * banana = boost::polymorphic_downcast<Banana*>(fruit);
|
|
||||||
...
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<h3>History</h3>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<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 "as is" without express
|
|
||||||
or implied warranty, and with no claim as to its suitability for any
|
|
||||||
purpose.</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@@ -1,91 +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>
|
|
||||||
|
|
||||||
# if SCHAR_MAX == LONG_MAX
|
|
||||||
# error "This test program doesn't work if SCHAR_MAX == LONG_MAX"
|
|
||||||
# endif
|
|
||||||
|
|
||||||
using namespace boost;
|
|
||||||
using std::cout;
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
struct Base
|
|
||||||
{
|
|
||||||
virtual char kind() { return 'B'; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Base2
|
|
||||||
{
|
|
||||||
virtual char kind2() { return '2'; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Derived : public Base, Base2
|
|
||||||
{
|
|
||||||
virtual char kind() { return 'D'; }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main( int argc, char * argv[] )
|
|
||||||
{
|
|
||||||
# ifdef NDEBUG
|
|
||||||
cout << "NDEBUG is defined\n";
|
|
||||||
# else
|
|
||||||
cout << "NDEBUG is not defined\n";
|
|
||||||
# endif
|
|
||||||
|
|
||||||
cout << "\nBeginning tests...\n";
|
|
||||||
|
|
||||||
// test polymorphic_cast ---------------------------------------------------//
|
|
||||||
|
|
||||||
// tests which should succeed
|
|
||||||
Base * base = new Derived;
|
|
||||||
Base2 * base2 = 0;
|
|
||||||
Derived * derived = 0;
|
|
||||||
derived = polymorphic_downcast<Derived*>( base ); // downcast
|
|
||||||
assert( derived->kind() == 'D' );
|
|
||||||
|
|
||||||
derived = 0;
|
|
||||||
derived = polymorphic_cast<Derived*>( base ); // downcast, throw on error
|
|
||||||
assert( derived->kind() == 'D' );
|
|
||||||
|
|
||||||
base2 = polymorphic_cast<Base2*>( base ); // crosscast
|
|
||||||
assert( base2->kind2() == '2' );
|
|
||||||
|
|
||||||
// tests which should result in errors being detected
|
|
||||||
int err_count = 0;
|
|
||||||
base = new Base;
|
|
||||||
|
|
||||||
if ( argc > 1 && *argv[1] == '1' )
|
|
||||||
{ derived = polymorphic_downcast<Derived*>( base ); } // #1 assert failure
|
|
||||||
|
|
||||||
bool caught_exception = false;
|
|
||||||
try { derived = polymorphic_cast<Derived*>( base ); }
|
|
||||||
catch (std::bad_cast)
|
|
||||||
{ cout<<"caught bad_cast\n"; caught_exception = true; }
|
|
||||||
if ( !caught_exception ) ++err_count;
|
|
||||||
// the following is just so generated code can be inspected
|
|
||||||
if ( derived->kind() == 'B' ) ++err_count;
|
|
||||||
|
|
||||||
cout << err_count << " errors detected\nTest "
|
|
||||||
<< (err_count==0 ? "passed\n" : "failed\n");
|
|
||||||
return err_count;
|
|
||||||
} // main
|
|
@@ -1,107 +0,0 @@
|
|||||||
// 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)
|
|
||||||
|
|
||||||
// See http://www.boost.org/libs/conversion for 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.
|
|
||||||
// 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)
|
|
||||||
// 15 Jul 00 Suppress numeric_cast warnings for GCC, Borland and MSVC
|
|
||||||
// (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
|
|
||||||
// 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.
|
|
||||||
// 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.
|
|
||||||
// 3 Aug 99 Initial version
|
|
||||||
|
|
||||||
#ifndef BOOST_CAST_HPP
|
|
||||||
#define BOOST_CAST_HPP
|
|
||||||
|
|
||||||
# include <boost/config.hpp>
|
|
||||||
# include <boost/assert.hpp>
|
|
||||||
# include <typeinfo>
|
|
||||||
# include <boost/type.hpp>
|
|
||||||
# include <boost/limits.hpp>
|
|
||||||
# include <boost/detail/select_type.hpp>
|
|
||||||
|
|
||||||
// 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
|
|
||||||
# define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::type<Target>* = 0
|
|
||||||
# else
|
|
||||||
# define BOOST_EXPLICIT_DEFAULT_TARGET
|
|
||||||
# endif
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
// See the documentation for descriptions of how to choose between
|
|
||||||
// static_cast<>, dynamic_cast<>, polymorphic_cast<> and polymorphic_downcast<>
|
|
||||||
|
|
||||||
// polymorphic_cast --------------------------------------------------------//
|
|
||||||
|
|
||||||
// Runtime checked polymorphic downcasts and crosscasts.
|
|
||||||
// Suggested in The C++ Programming Language, 3rd Ed, Bjarne Stroustrup,
|
|
||||||
// section 15.8 exercise 1, page 425.
|
|
||||||
|
|
||||||
template <class Target, class Source>
|
|
||||||
inline Target polymorphic_cast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
|
|
||||||
{
|
|
||||||
Target tmp = dynamic_cast<Target>(x);
|
|
||||||
if ( tmp == 0 ) throw std::bad_cast();
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// polymorphic_downcast ----------------------------------------------------//
|
|
||||||
|
|
||||||
// BOOST_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.
|
|
||||||
|
|
||||||
// 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
|
|
||||||
return static_cast<Target>(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
# undef BOOST_EXPLICIT_DEFAULT_TARGET
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
# include <boost/numeric/conversion/cast.hpp>
|
|
||||||
|
|
||||||
#endif // BOOST_CAST_HPP
|
|
38
index.html
38
index.html
@@ -1,38 +0,0 @@
|
|||||||
<html>
|
|
||||||
|
|
||||||
<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="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
|
|
||||||
Conversion Library</h1>
|
|
||||||
|
|
||||||
<p>The Conversion Library improves program safety and clarity by performing
|
|
||||||
otherwise messy conversions. It includes cast-style function templates designed to complement the C++
|
|
||||||
Standard's built-in casts.</p>
|
|
||||||
<p>To reduce coupling, particularly to standard library IOStreams, the Boost
|
|
||||||
Conversion Library is
|
|
||||||
supplied by several headers:</p>
|
|
||||||
<ul>
|
|
||||||
<li>The <a href="cast.htm">boost/cast</a> header provides <b>polymorphic_cast<></b>
|
|
||||||
and <b>polymorphic_downcast<></b> to perform safe casting between
|
|
||||||
polymorphic types.<br>
|
|
||||||
</li>
|
|
||||||
<li>The <a href="lexical_cast.htm">boost/lexical_cast</a> header provides <b>lexical_cast<></b>
|
|
||||||
general literal text conversions, such as an <code>int</code> represented as
|
|
||||||
a <code>string</code>, or vice-versa.</li>
|
|
||||||
</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" -->
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
234
lexical_cast.htm
234
lexical_cast.htm
@@ -1,234 +0,0 @@
|
|||||||
<!-- 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[])
|
|
||||||
{
|
|
||||||
using boost::lexical_cast;
|
|
||||||
using boost::bad_lexical_cast;
|
|
||||||
|
|
||||||
std::vector<short> args;
|
|
||||||
|
|
||||||
while(*++argv)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
args.push_back(lexical_cast<short>(*argv));
|
|
||||||
}
|
|
||||||
catch(bad_lexical_cast &)
|
|
||||||
{
|
|
||||||
args.push_back(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
...
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</blockquote>The following example uses numeric data in a string expression: <blockquote>
|
|
||||||
<pre>void log_message(const std::string &);
|
|
||||||
|
|
||||||
void log_errno(int yoko)
|
|
||||||
{
|
|
||||||
log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</blockquote>
|
|
||||||
<hr>
|
|
||||||
<h2><a name="synopsis">Synopsis</a></h2>
|
|
||||||
Library features defined in <a href="../../boost/lexical_cast.hpp"><code>"boost/lexical_cast.hpp"</code></a>:
|
|
||||||
<blockquote>
|
|
||||||
<pre>namespace boost
|
|
||||||
{
|
|
||||||
class <a href="#bad_lexical_cast">bad_lexical_cast</a>;
|
|
||||||
template<typename Target, typename Source>
|
|
||||||
Target <a href="#lexical_cast">lexical_cast</a>(const Source& arg);
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</blockquote>Unit test defined in <a href="lexical_cast_test.cpp"><code>"lexical_cast_test.cpp"</code></a>.
|
|
||||||
<p>
|
|
||||||
<hr>
|
|
||||||
<h2><a name="lexical_cast"><code>lexical_cast</code></a></h2>
|
|
||||||
<blockquote>
|
|
||||||
<pre>template<typename Target, typename Source>
|
|
||||||
Target lexical_cast(const 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>></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<<</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>></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
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
... // <i>same member function interface as</i> std::exception
|
|
||||||
};
|
|
||||||
</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>
|
|
||||||
</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<std::string>("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<char *>("Goodbye, World")</code>
|
|
||||||
now throws an exception instead of causing undefined behavior.
|
|
||||||
</ul>
|
|
||||||
<p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<div align="right"><small><i>© Copyright Kevlin Henney, 2000–2005</i></small></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@@ -1,320 +0,0 @@
|
|||||||
// Unit test for boost::lexical_cast.
|
|
||||||
//
|
|
||||||
// See http://www.boost.org for most recent version, including documentation.
|
|
||||||
//
|
|
||||||
// Copyright Terje Sletteb<65> 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.
|
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
using namespace boost;
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
unit_test::test_suite *init_unit_test_suite(int, char *[])
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_conversion_to_char()
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_conversion_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_conversion_to_double()
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_conversion_to_bool()
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_conversion_to_string()
|
|
||||||
{
|
|
||||||
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("")));
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_conversion_from_to_wchar_t_alias()
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
@@ -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 ;
|
|
||||||
}
|
|
308
test.hpp
308
test.hpp
@@ -1,308 +0,0 @@
|
|||||||
// what: simple unit test framework
|
|
||||||
// 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
|
|
||||||
|
|
||||||
#include <exception>
|
|
||||||
#include <iostream>
|
|
||||||
#include <strstream> // for out-of-the-box g++
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace test // test tuple comprises name and nullary function (object)
|
|
||||||
{
|
|
||||||
template<typename string_type, typename function_type>
|
|
||||||
struct test
|
|
||||||
{
|
|
||||||
string_type name;
|
|
||||||
function_type action;
|
|
||||||
|
|
||||||
static test make(string_type name, function_type action)
|
|
||||||
{
|
|
||||||
test result; // MSVC aggreggate initializer bugs
|
|
||||||
result.name = name;
|
|
||||||
result.action = action;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace test // failure exception used to indicate checked test failures
|
|
||||||
{
|
|
||||||
class failure : public std::exception
|
|
||||||
{
|
|
||||||
public: // struction (default cases are OK)
|
|
||||||
|
|
||||||
failure(const std::string & why)
|
|
||||||
: reason(why)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
{
|
|
||||||
return reason.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
private: // representation
|
|
||||||
|
|
||||||
std::string reason;
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace test // not_implemented exception used to mark unimplemented tests
|
|
||||||
{
|
|
||||||
class not_implemented : public std::exception
|
|
||||||
{
|
|
||||||
public: // usage (default ctor and dtor are OK)
|
|
||||||
|
|
||||||
virtual const char * what() const throw()
|
|
||||||
{
|
|
||||||
return "not implemented";
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace test // test utilities
|
|
||||||
{
|
|
||||||
inline void check(bool condition, const std::string & description)
|
|
||||||
{
|
|
||||||
if(!condition)
|
|
||||||
{
|
|
||||||
throw failure(description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void check_true(bool value, const std::string & description)
|
|
||||||
{
|
|
||||||
check(value, "expected true: " + description);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void check_false(bool value, const std::string & description)
|
|
||||||
{
|
|
||||||
check(!value, "expected false: " + description);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename lhs_type, typename rhs_type>
|
|
||||||
void check_equal(
|
|
||||||
const lhs_type & lhs, const rhs_type & rhs,
|
|
||||||
const std::string & description)
|
|
||||||
{
|
|
||||||
check(lhs == rhs, "expected equal values: " + description);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename lhs_type, typename rhs_type>
|
|
||||||
void check_unequal(
|
|
||||||
const lhs_type & lhs, const rhs_type & rhs,
|
|
||||||
const std::string & description)
|
|
||||||
{
|
|
||||||
check(lhs != rhs, "expected unequal values: " + 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)
|
|
||||||
{
|
|
||||||
check(ptr != 0, "expected non-null pointer: " + description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define TEST_CHECK_THROW(expression, exception, description) \
|
|
||||||
try \
|
|
||||||
{ \
|
|
||||||
expression; \
|
|
||||||
throw ::test::failure(description); \
|
|
||||||
} \
|
|
||||||
catch(exception &) \
|
|
||||||
{ \
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace test // memory tracking (enabled if test new and delete linked in)
|
|
||||||
{
|
|
||||||
class allocations
|
|
||||||
{
|
|
||||||
public: // singleton access
|
|
||||||
|
|
||||||
static allocations & instance()
|
|
||||||
{
|
|
||||||
static allocations singleton;
|
|
||||||
return singleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
public: // logging
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
alloc_count = dealloc_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void allocation()
|
|
||||||
{
|
|
||||||
++alloc_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocation()
|
|
||||||
{
|
|
||||||
++dealloc_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public: // reporting
|
|
||||||
|
|
||||||
unsigned long allocated() const
|
|
||||||
{
|
|
||||||
return alloc_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long deallocated() const
|
|
||||||
{
|
|
||||||
return dealloc_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool balanced() const
|
|
||||||
{
|
|
||||||
return alloc_count == dealloc_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
private: // structors (default dtor is fine)
|
|
||||||
|
|
||||||
allocations()
|
|
||||||
: alloc_count(0), dealloc_count(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private: // prevention
|
|
||||||
|
|
||||||
allocations(const allocations &);
|
|
||||||
allocations & operator=(const allocations &);
|
|
||||||
|
|
||||||
private: // state
|
|
||||||
|
|
||||||
unsigned long alloc_count, dealloc_count;
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace test // tester is the driver class for a sequence of tests
|
|
||||||
{
|
|
||||||
template<typename test_iterator>
|
|
||||||
class tester
|
|
||||||
{
|
|
||||||
public: // structors (default destructor is OK)
|
|
||||||
|
|
||||||
tester(test_iterator first_test, test_iterator after_last_test)
|
|
||||||
: begin(first_test), end(after_last_test)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public: // usage
|
|
||||||
|
|
||||||
bool operator()(); // returns true if all tests passed
|
|
||||||
|
|
||||||
private: // representation
|
|
||||||
|
|
||||||
test_iterator begin, end;
|
|
||||||
|
|
||||||
private: // prevention
|
|
||||||
|
|
||||||
tester(const tester &);
|
|
||||||
tester &operator=(const tester &);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename test_iterator>
|
|
||||||
bool tester<test_iterator>::operator()()
|
|
||||||
{
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
unsigned long passed = 0, failed = 0, unimplemented = 0;
|
|
||||||
|
|
||||||
for(test_iterator current = begin; current != end; ++current)
|
|
||||||
{
|
|
||||||
cerr << "[" << current->name << "] " << flush;
|
|
||||||
string result = "passed"; // optimistic
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
allocations::instance().clear();
|
|
||||||
current->action();
|
|
||||||
|
|
||||||
if(!allocations::instance().balanced())
|
|
||||||
{
|
|
||||||
unsigned long allocated = allocations::instance().allocated();
|
|
||||||
unsigned long deallocated = allocations::instance().deallocated();
|
|
||||||
ostrstream report;
|
|
||||||
report << "new/delete ("
|
|
||||||
<< allocated << " allocated, "
|
|
||||||
<< deallocated << " deallocated)"
|
|
||||||
<< ends;
|
|
||||||
const char * text = report.str();
|
|
||||||
report.freeze(false);
|
|
||||||
throw failure(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
++passed;
|
|
||||||
}
|
|
||||||
catch(const failure & caught)
|
|
||||||
{
|
|
||||||
(result = "failed: ") += caught.what();
|
|
||||||
++failed;
|
|
||||||
}
|
|
||||||
catch(const not_implemented &)
|
|
||||||
{
|
|
||||||
result = "not implemented";
|
|
||||||
++unimplemented;
|
|
||||||
}
|
|
||||||
catch(const exception & caught)
|
|
||||||
{
|
|
||||||
(result = "exception: ") += caught.what();
|
|
||||||
++failed;
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
result = "failed with unknown exception";
|
|
||||||
++failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
cerr << result << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
cerr << passed + failed << " tests: "
|
|
||||||
<< passed << " passed, "
|
|
||||||
<< failed << " failed";
|
|
||||||
|
|
||||||
if(unimplemented)
|
|
||||||
{
|
|
||||||
cerr << " (" << unimplemented << " not implemented)";
|
|
||||||
}
|
|
||||||
|
|
||||||
cerr << endl;
|
|
||||||
|
|
||||||
return failed == 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 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)
|
|
@@ -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 ]
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
@@ -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();
|
|
||||||
}
|
|
@@ -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");
|
|
||||||
}
|
|
Reference in New Issue
Block a user