mirror of
https://github.com/boostorg/conversion.git
synced 2026-08-06 21:44:08 +02:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c2b4875ef0 | |||
| 2ce20c872e | |||
| 49c0b2f333 | |||
| e9a5ac6d7a | |||
| ee3f643c5e | |||
| d44a6fcf8b | |||
| ac6e41d676 | |||
| 4224fa5deb | |||
| d6eea4ef81 | |||
| 37d07617d1 | |||
| bfeb60c400 | |||
| 78f1acc5ff | |||
| abf3aa23de | |||
| 06e7d986d2 | |||
| 74fc01da7e | |||
| 80e9edcb29 | |||
| 17ca3a4493 | |||
| e5a0aec661 | |||
| 8cec2cc291 | |||
| 027a566e09 | |||
| 9a29a753e8 | |||
| cb2bd8076d | |||
| 1637edf8ca | |||
| 72d69ef6ad | |||
| 1470210523 | |||
| 0b19a0ae27 | |||
| 3ab685475c | |||
| e66d58e6de | |||
| e331fc2a21 | |||
| 2a65633517 | |||
| 7a388cb1a6 | |||
| 461dce3851 | |||
| cfe358b570 | |||
| caa875505e | |||
| 462025d8e6 |
@@ -3,7 +3,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
"Microsoft FrontPage 5.0">
|
||||
<meta http-equiv="Content-Type" content=
|
||||
"text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
@@ -19,10 +19,9 @@
|
||||
|
||||
<h2><a name="Cast Functions">Cast Functions</a></h2>
|
||||
|
||||
<p>The header <a href="../../boost/cast.hpp">boost/cast.hpp</a> 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
|
||||
<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
|
||||
@@ -34,43 +33,50 @@
|
||||
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 <b>Y</b> diagram hierarchy.</p>
|
||||
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 <b>static_cast</b> can be used for efficiently
|
||||
<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 <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>
|
||||
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 <b>dynamic_cast</b> can be used for downcasts and
|
||||
<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 <b>dynamic_cast</b>, which
|
||||
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 <b>polymorphic_cast</b>
|
||||
template performs a <b>dynamic_cast</b> on a pointer, and throws an
|
||||
exception if the <b>dynamic_cast</b> returns 0.</p>
|
||||
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 <b>polymorphic_downcast</b> is preferred when debug-mode tests will
|
||||
cover 100% of the object types possibly cast and when non-debug-mode
|
||||
efficiency is an issue. If these two conditions are not present,
|
||||
<b>polymorphic_cast</b> is preferred. It must also be used for
|
||||
crosscasts. It does an assert( dynamic_cast<Derived>(x) == x )
|
||||
where x is the base pointer, ensuring that not only is a non-zero pointer
|
||||
returned, but also that it correct in the presence of multiple
|
||||
inheritance. <b>Warning:</b>: Because <b>polymorphic_downcast</b> uses
|
||||
assert(), it violates the one definition rule (ODR) if NDEBUG is
|
||||
inconsistently defined across translation units. [See ISO Std 3.2]</p>
|
||||
<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 <b>dynamic_cast</b> must be used to cast references
|
||||
<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>
|
||||
@@ -78,8 +84,7 @@
|
||||
<h3>polymorphic_cast and polymorphic_downcast synopsis</h3>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
namespace boost {
|
||||
<pre>namespace boost {
|
||||
|
||||
template <class Derived, class Base>
|
||||
inline Derived polymorphic_cast(Base* x);
|
||||
@@ -98,8 +103,7 @@ inline Derived polymorphic_downcast(Base* x);
|
||||
<h3>polymorphic_downcast example</h3>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <boost/cast.hpp>
|
||||
<pre>#include <boost/cast.hpp>
|
||||
...
|
||||
class Fruit { public: virtual ~Fruit(){}; ... };
|
||||
class Banana : public Fruit { ... };
|
||||
@@ -111,85 +115,20 @@ void f( Fruit * fruit ) {
|
||||
</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<>::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 {
|
||||
|
||||
class bad_numeric_cast : public std::bad_cast {...};
|
||||
|
||||
template<typename Target, typename Source>
|
||||
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<Target>(arg)
|
||||
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>numeric_cast example</h3>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <boost/cast.hpp>
|
||||
using namespace boost::cast;
|
||||
|
||||
void ariane(double vx)
|
||||
{
|
||||
...
|
||||
unsigned short dx = numeric_cast<unsigned short>(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 "The C++
|
||||
<p><code>polymorphic_cast</code> was suggested by Bjarne Stroustrup in "The C++
|
||||
Programming Language".<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>
|
||||
<code>polymorphic_downcast</code> was contributed by <a href=
|
||||
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>.<code><br>
|
||||
An old
|
||||
numeric_cast</code> that was contributed by <a href=
|
||||
"http://www.boost.org/people/kevlin_henney.htm">Kevlin Henney</a> is now superseeded by the <a href="../numeric/conversion/doc/html/index.html">Boost Numeric Conversion Library</a></p>
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
|
||||
-->06 January, 2001
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="38320"
|
||||
-->June 23, 2005<!--webbot bot="Timestamp" endspan i-checksum="30348"
|
||||
--></p>
|
||||
|
||||
<p>© Copyright boost.org 1999. Permission to copy, use, modify, sell
|
||||
@@ -198,5 +137,4 @@ void ariane(double vx)
|
||||
or implied warranty, and with no claim as to its suitability for any
|
||||
purpose.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
+18
-295
@@ -1,6 +1,6 @@
|
||||
// boost cast.hpp header file ----------------------------------------------//
|
||||
|
||||
// (C) Copyright Kevlin Henney and Dave Abrahams 1999.
|
||||
// (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)
|
||||
@@ -8,9 +8,10 @@
|
||||
// See http://www.boost.org/libs/conversion for Documentation.
|
||||
|
||||
// Revision History
|
||||
// 02 Apr 01 Removed BOOST_NO_LIMITS workarounds and included
|
||||
// <boost/limits.hpp> instead (the workaround did not
|
||||
// actually compile when BOOST_NO_LIMITS was defined in
|
||||
// 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
|
||||
@@ -26,14 +27,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.
|
||||
@@ -43,7 +44,7 @@
|
||||
#define BOOST_CAST_HPP
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <cassert>
|
||||
# include <boost/assert.hpp>
|
||||
# include <typeinfo>
|
||||
# include <boost/type.hpp>
|
||||
# include <boost/limits.hpp>
|
||||
@@ -54,7 +55,7 @@
|
||||
// appear in the function's argument list.
|
||||
//
|
||||
// TODO: Add this to config.hpp?
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200 // 1200 = VC6
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC < 1300
|
||||
# define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::type<Target>* = 0
|
||||
# else
|
||||
# define BOOST_EXPLICIT_DEFAULT_TARGET
|
||||
@@ -68,7 +69,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>
|
||||
@@ -81,304 +82,26 @@ namespace boost
|
||||
|
||||
// polymorphic_downcast ----------------------------------------------------//
|
||||
|
||||
// assert() checked polymorphic downcast. Crosscasts prohibited.
|
||||
// BOOST_ASSERT() checked polymorphic downcast. Crosscasts prohibited.
|
||||
|
||||
// WARNING: Because this cast uses assert(), it violates the One Definition
|
||||
// Rule if NDEBUG is inconsistently defined across translation units.
|
||||
// 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)
|
||||
{
|
||||
assert( dynamic_cast<Target>(x) == x ); // detect logic error
|
||||
BOOST_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 ------------------------------------------------------------//
|
||||
|
||||
#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_SGI_CPP_LIMITS)
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct signed_numeric_limits : std::numeric_limits<T>
|
||||
{
|
||||
static inline T min BOOST_PREVENT_MACRO_SUBSTITUTION ()
|
||||
{
|
||||
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)();
|
||||
};
|
||||
};
|
||||
|
||||
// Move to namespace boost in utility.hpp?
|
||||
template <class T, bool specialized>
|
||||
struct fixed_numeric_limits_base
|
||||
: public if_true< std::numeric_limits<T>::is_signed >
|
||||
::BOOST_NESTED_TEMPLATE then< signed_numeric_limits<T>,
|
||||
std::numeric_limits<T>
|
||||
>::type
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
struct fixed_numeric_limits
|
||||
: fixed_numeric_limits_base<T,(std::numeric_limits<T>::is_specialized)>
|
||||
{};
|
||||
|
||||
# ifdef BOOST_HAS_LONG_LONG
|
||||
// cover implementations which supply no specialization for long
|
||||
// long / unsigned long long. Not intended to be full
|
||||
// numeric_limits replacements, but good enough for numeric_cast<>
|
||||
template <>
|
||||
struct fixed_numeric_limits_base< ::boost::long_long_type, false>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
|
||||
BOOST_STATIC_CONSTANT(bool, is_signed = true);
|
||||
static ::boost::long_long_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
|
||||
{
|
||||
# ifdef LONGLONG_MAX
|
||||
return LONGLONG_MAX;
|
||||
# else
|
||||
return 9223372036854775807LL; // hope this is portable
|
||||
# endif
|
||||
}
|
||||
|
||||
static ::boost::long_long_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
|
||||
{
|
||||
# ifdef LONGLONG_MIN
|
||||
return LONGLONG_MIN;
|
||||
# else
|
||||
return -( 9223372036854775807LL )-1; // hope this is portable
|
||||
# endif
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fixed_numeric_limits_base< ::boost::ulong_long_type, false>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
|
||||
BOOST_STATIC_CONSTANT(bool, is_signed = false);
|
||||
static ::boost::ulong_long_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
|
||||
{
|
||||
# ifdef ULONGLONG_MAX
|
||||
return ULONGLONG_MAX;
|
||||
# else
|
||||
return 0xffffffffffffffffULL; // hope this is portable
|
||||
# endif
|
||||
}
|
||||
|
||||
static ::boost::ulong_long_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; }
|
||||
};
|
||||
# endif
|
||||
} // 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; }
|
||||
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200
|
||||
// MSVC6 can't static_cast unsigned __int64 -> floating types
|
||||
# define BOOST_UINT64_CAST(src_type) \
|
||||
static inline bool check(src_type x, unsigned __int64) \
|
||||
{ \
|
||||
if (x < 0) return false; \
|
||||
unsigned __int64 y = static_cast<unsigned __int64>(x); \
|
||||
bool odd = y & 0x1; \
|
||||
__int64 div2 = static_cast<__int64>(y >> 1); \
|
||||
return ((static_cast<src_type>(div2) * 2.0) + odd) != x; \
|
||||
}
|
||||
|
||||
BOOST_UINT64_CAST(long double);
|
||||
BOOST_UINT64_CAST(double);
|
||||
BOOST_UINT64_CAST(float);
|
||||
# undef BOOST_UINT64_CAST
|
||||
# endif
|
||||
};
|
||||
|
||||
template<>
|
||||
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
|
||||
|
||||
// Move to namespace boost in utility.hpp?
|
||||
template <class T>
|
||||
struct fixed_numeric_limits : public std::numeric_limits<T>
|
||||
{
|
||||
static inline T min BOOST_PREVENT_MACRO_SUBSTITUTION ()
|
||||
{
|
||||
return std::numeric_limits<T>::is_signed && (std::numeric_limits<T>::min)() >= 0
|
||||
? T(-(std::numeric_limits<T>::max)()) : (std::numeric_limits<T>::min)();
|
||||
}
|
||||
};
|
||||
|
||||
# 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)
|
||||
{
|
||||
// typedefs abbreviating respective trait classes
|
||||
typedef detail::fixed_numeric_limits<Source> arg_traits;
|
||||
typedef detail::fixed_numeric_limits<Target> result_traits;
|
||||
|
||||
#if defined(BOOST_STRICT_CONFIG) \
|
||||
|| (!defined(__HP_aCC) || __HP_aCC > 33900) \
|
||||
&& (!defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) \
|
||||
|| defined(BOOST_SGI_CPP_LIMITS))
|
||||
// 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
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
// Copyright Alexander Nasonov & Paul A. Bristow 2006.
|
||||
|
||||
// Use, modification and distribution are subject to 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 BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
|
||||
|
||||
#include <climits>
|
||||
#include <ios>
|
||||
#include <limits>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/integer_traits.hpp>
|
||||
|
||||
#ifndef BOOST_NO_IS_ABSTRACT
|
||||
// Fix for SF:1358600 - lexical_cast & pure virtual functions & VC 8 STL
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_abstract.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || \
|
||||
(defined(BOOST_MSVC) && (BOOST_MSVC<1310))
|
||||
|
||||
#define BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
||||
#include <boost/assert.hpp>
|
||||
#else
|
||||
#include <boost/static_assert.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace detail {
|
||||
|
||||
class lcast_abstract_stub {};
|
||||
|
||||
#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
||||
// Calculate an argument to pass to std::ios_base::precision from
|
||||
// lexical_cast. See alternative implementation for broken standard
|
||||
// libraries in lcast_get_precision below. Keep them in sync, please.
|
||||
template<class T>
|
||||
struct lcast_precision
|
||||
{
|
||||
#ifdef BOOST_NO_IS_ABSTRACT
|
||||
typedef std::numeric_limits<T> limits; // No fix for SF:1358600.
|
||||
#else
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
|
||||
boost::is_abstract<T>
|
||||
, std::numeric_limits<lcast_abstract_stub>
|
||||
, std::numeric_limits<T>
|
||||
>::type limits;
|
||||
#endif
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, use_default_precision =
|
||||
!limits::is_specialized || limits::is_exact
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized_bin =
|
||||
!use_default_precision &&
|
||||
limits::radix == 2 && limits::digits > 0
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized_dec =
|
||||
!use_default_precision &&
|
||||
limits::radix == 10 && limits::digits10 > 0
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(std::streamsize, streamsize_max =
|
||||
boost::integer_traits<std::streamsize>::const_max
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(unsigned int, precision_dec = limits::digits10 + 1U);
|
||||
|
||||
BOOST_STATIC_ASSERT(!is_specialized_dec ||
|
||||
precision_dec <= streamsize_max + 0UL
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(unsigned long, precision_bin =
|
||||
2UL + limits::digits * 30103UL / 100000UL
|
||||
);
|
||||
|
||||
BOOST_STATIC_ASSERT(!is_specialized_bin ||
|
||||
(limits::digits + 0UL < ULONG_MAX / 30103UL &&
|
||||
precision_bin > limits::digits10 + 0UL &&
|
||||
precision_bin <= streamsize_max + 0UL)
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(std::streamsize, value =
|
||||
is_specialized_bin ? precision_bin
|
||||
: is_specialized_dec ? precision_dec : 6
|
||||
);
|
||||
};
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline std::streamsize lcast_get_precision(T* = 0)
|
||||
{
|
||||
#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
||||
return lcast_precision<T>::value;
|
||||
#else // Follow lcast_precision algorithm at run-time:
|
||||
|
||||
#ifdef BOOST_NO_IS_ABSTRACT
|
||||
typedef std::numeric_limits<T> limits; // No fix for SF:1358600.
|
||||
#else
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
|
||||
boost::is_abstract<T>
|
||||
, std::numeric_limits<lcast_abstract_stub>
|
||||
, std::numeric_limits<T>
|
||||
>::type limits;
|
||||
#endif
|
||||
|
||||
bool const use_default_precision =
|
||||
!limits::is_specialized || limits::is_exact;
|
||||
|
||||
if(!use_default_precision)
|
||||
{ // Includes all built-in floating-point types, float, double ...
|
||||
// and UDT types for which digits (significand bits) is defined (not zero)
|
||||
|
||||
bool const is_specialized_bin =
|
||||
limits::radix == 2 && limits::digits > 0;
|
||||
bool const is_specialized_dec =
|
||||
limits::radix == 10 && limits::digits10 > 0;
|
||||
std::streamsize const streamsize_max =
|
||||
(boost::integer_traits<std::streamsize>::max)();
|
||||
|
||||
if(is_specialized_bin)
|
||||
{ // Floating-point types with
|
||||
// limits::digits defined by the specialization.
|
||||
|
||||
unsigned long const digits = limits::digits;
|
||||
unsigned long const precision = 2UL + digits * 30103UL / 100000UL;
|
||||
// unsigned long is selected because it is at least 32-bits
|
||||
// and thus ULONG_MAX / 30103UL is big enough for all types.
|
||||
BOOST_ASSERT(
|
||||
digits < ULONG_MAX / 30103UL &&
|
||||
precision > limits::digits10 + 0UL &&
|
||||
precision <= streamsize_max + 0UL
|
||||
);
|
||||
return precision;
|
||||
}
|
||||
else if(is_specialized_dec)
|
||||
{ // Decimal Floating-point type, most likely a User Defined Type
|
||||
// rather than a real floating-point hardware type.
|
||||
unsigned int const precision = limits::digits10 + 1U;
|
||||
BOOST_ASSERT(precision <= streamsize_max + 0UL);
|
||||
return precision;
|
||||
}
|
||||
}
|
||||
|
||||
// Integral type (for which precision has no effect)
|
||||
// or type T for which limits is NOT specialized,
|
||||
// so assume stream precision remains the default 6 decimal digits.
|
||||
// Warning: if your User-defined Floating-point type T is NOT specialized,
|
||||
// then you may lose accuracy by only using 6 decimal digits.
|
||||
// To avoid this, you need to specialize T with either
|
||||
// radix == 2 and digits == the number of significand bits,
|
||||
// OR
|
||||
// radix = 10 and digits10 == the number of decimal digits.
|
||||
|
||||
return 6;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void lcast_set_precision(std::ios_base& stream, T*)
|
||||
{
|
||||
stream.precision(lcast_get_precision<T>());
|
||||
}
|
||||
|
||||
template<class Source, class Target>
|
||||
inline void lcast_set_precision(std::ios_base& stream, Source*, Target*)
|
||||
{
|
||||
std::streamsize const s = lcast_get_precision((Source*)0);
|
||||
std::streamsize const t = lcast_get_precision((Target*)0);
|
||||
stream.precision(s > t ? s : t);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
|
||||
|
||||
Executable → Regular
+1
-7
@@ -23,13 +23,7 @@ inline T implicit_cast (typename mpl::identity<T>::type x) {
|
||||
//template <typename T>
|
||||
//void implicit_cast (...);
|
||||
|
||||
// Macro for when you need a constant expression (Gennaro Prota)
|
||||
#define BOOST_IMPLICIT_CAST(dst_type, expr) \
|
||||
( sizeof( implicit_cast<dst_type>(expr) ) \
|
||||
, \
|
||||
static_cast<dst_type>(expr) \
|
||||
)
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // IMPLICIT_CAST_DWA200356_HPP
|
||||
|
||||
+1033
-31
File diff suppressed because it is too large
Load Diff
+4
-5
@@ -3,7 +3,7 @@
|
||||
<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 4.0">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Boost Conversion Library</title>
|
||||
</head>
|
||||
@@ -22,8 +22,7 @@ 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, and <b> numeric_cast</b><i><></i> to perform safe casting
|
||||
between numeric types.<br>
|
||||
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
|
||||
@@ -31,9 +30,9 @@ supplied by several headers:</p>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED"
|
||||
S-Format="%d %B, %Y" startspan -->06 January, 2001<!--webbot bot="Timestamp" endspan i-checksum="38320" -->
|
||||
S-Format="%d %B, %Y" startspan -->June 23, 2005<!--webbot bot="Timestamp" endspan i-checksum="30348" -->
|
||||
</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
+83
-36
@@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<title>lexical_cast</title>
|
||||
<meta name="author" content="Kevlin Henney, mailto:kevlin@curbralan.com">
|
||||
<meta name="generator" content="Microsoft FrontPage 4.0">
|
||||
<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
|
||||
@@ -20,6 +20,10 @@
|
||||
<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="#faq">Frequently Asked Questions</a></li>
|
||||
<li>
|
||||
<a href="#references">References</a></li>
|
||||
<li>
|
||||
<a href="#changes">Changes</a></li>
|
||||
</ul>
|
||||
@@ -77,7 +81,7 @@
|
||||
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>
|
||||
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
|
||||
@@ -89,8 +93,7 @@
|
||||
<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[])
|
||||
<pre>int main(int argc, char * argv[])
|
||||
{
|
||||
using boost::lexical_cast;
|
||||
using boost::bad_lexical_cast;
|
||||
@@ -112,8 +115,7 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
</pre>
|
||||
</blockquote>The following example uses numeric data in a string expression: <blockquote>
|
||||
<pre>
|
||||
void log_message(const std::string &);
|
||||
<pre>void log_message(const std::string &);
|
||||
|
||||
void log_errno(int yoko)
|
||||
{
|
||||
@@ -125,12 +127,11 @@ void log_errno(int yoko)
|
||||
<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
|
||||
<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>(Source arg);
|
||||
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>.
|
||||
@@ -138,9 +139,8 @@ namespace boost
|
||||
<hr>
|
||||
<h2><a name="lexical_cast"><code>lexical_cast</code></a></h2>
|
||||
<blockquote>
|
||||
<pre>
|
||||
template<typename Target, typename Source>
|
||||
Target lexical_cast(Source arg);
|
||||
<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.
|
||||
@@ -164,7 +164,7 @@ template<typename Target, typename Source>
|
||||
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].
|
||||
<code>Target</code> is <i>CopyConstructible</i> [20.1.3].
|
||||
</li>
|
||||
<li>
|
||||
<code>Target</code> is <i>DefaultConstructible</i>, meaning that it is possible
|
||||
@@ -186,8 +186,7 @@ template<typename Target, typename Source>
|
||||
<hr>
|
||||
<h2><a name="bad_lexical_cast"><code>bad_lexical_cast</code></a></h2>
|
||||
<blockquote>
|
||||
<pre>
|
||||
class bad_lexical_cast : public std::bad_cast
|
||||
<pre>class bad_lexical_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
... // <i>same member function interface as</i> std::exception
|
||||
@@ -196,28 +195,76 @@ public:
|
||||
</blockquote>Exception used to indicate runtime <a href="#lexical_cast"><code>lexical_cast</code></a>
|
||||
failure.
|
||||
<hr>
|
||||
<h2><a name="changes">Changes</a></h2>
|
||||
<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.
|
||||
<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>.
|
||||
<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.
|
||||
<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>
|
||||
|
||||
<h2><a name="faq">Frequently Asked Questions</h2>
|
||||
<p> Q: Why does <code>lexical_cast<int8_t>("127")</code> throw <code>bad_lexical_cast</code>?
|
||||
<br> A: The type <code>int8_t</code> is a typedef to <code>char</code> or <code>signed char</code>.
|
||||
Lexical conversion to these types is simply reading a byte from source but since the source has
|
||||
more than one byte, the exception is thrown.
|
||||
<p>Please use other integer types such as <code>int</code> or <code>short int</code>. If bounds checking
|
||||
is important, you can also call <a href="../../libs/numeric/conversion/doc/numeric_cast.html">numeric_cast</a>:
|
||||
|
||||
<pre><a href="../../libs/numeric/conversion/doc/numeric_cast.html">numeric_cast</a><int8_t>(lexical_cast<int>("127"));</pre>
|
||||
|
||||
<p> Q: What does <code>lexical_cast<std::string></code> of an <code>int8_t</code> or <code>uint8_t</code> not do what I expect?
|
||||
<br> A: As above, note that <code>int8_t</code> and <code>uint8_t</code> are actually chars and are formatted as such. To avoid this, cast to an integer type first:
|
||||
|
||||
<pre>lexical_cast<std::string>(static_cast<int>(n));</pre>
|
||||
|
||||
<p> Q: The implementation always resets the <code>ios_base::skipws</code> flag of an underlying stream object. It breaks my <code>operator>></code> that works only in presence of this flag. Can you remove code that resets the flag?
|
||||
<br> A: May be in a future version. There is no requirement in <a href="#n1973">[N1973]</a> to reset the flag but remember that <a href="#n1973">[N1973]</a> is not yet accepted by the committee. By the way, it's a great opportunity to make your <code>operator>></code> conform to the standard. Read a good C++ book, study <code>std::sentry</code> and <a href="../../libs/io/doc/ios_state.html">ios_state_saver</a>.
|
||||
</ul>
|
||||
<h2><a name="references">References</h2>
|
||||
<ul type="square">
|
||||
<a name="n1973"></a><li> [N1973] Kevlin Henney, Beman Dawes, Lexical Conversion Library Proposal for TR2,
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1973.html">N1973</a>.
|
||||
<a name="tuning"></a><li> [Tuning] Alexander Nasonov, Fine Tuning for lexical_cast,
|
||||
<a href="http://www.accu.org/var/uploads/journals/overload74.pdf">Overload #74</a>,
|
||||
August 2006.</li>
|
||||
</ul>
|
||||
<h2><a name="changes">Changes</a></h2>
|
||||
<h3>August, October 2006:</h3>
|
||||
<ul type="square">
|
||||
<li>Better performance for many combinations of <code>Source</code> and <code>Target</code>
|
||||
types. Refer to <a href="#tuning">[Tuning]</a> for more details.
|
||||
</li>
|
||||
</ul>
|
||||
<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–2003</i></small></div>
|
||||
|
||||
<div align="right"><small><i>© Copyright Kevlin Henney, 2000–2005</i></small></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+534
-71
@@ -2,11 +2,14 @@
|
||||
//
|
||||
// See http://www.boost.org for most recent version, including documentation.
|
||||
//
|
||||
// Copyright Terje Slettebø and Kevlin Henney, 2003.
|
||||
// Copyright Terje Slettebø and Kevlin Henney, 2005.
|
||||
// Copyright Alexander Nasonov, 2006.
|
||||
//
|
||||
// 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>
|
||||
|
||||
@@ -17,16 +20,41 @@
|
||||
#endif
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/floating_point_comparison.hpp>
|
||||
#include <boost/test/included/unit_test_framework.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#if defined(BOOST_NO_STRINGSTREAM) || \
|
||||
defined(BOOST_NO_STD_WSTRING) || \
|
||||
defined(BOOST_NO_STD_LOCALE) || \
|
||||
defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
defined(BOOST_NO_STD_LOCALE)
|
||||
#define DISABLE_WIDE_CHAR_SUPPORT
|
||||
#endif
|
||||
|
||||
#if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) \
|
||||
&& !(defined(BOOST_MSVC) && BOOST_MSVC < 1300)
|
||||
#define LCAST_TEST_LONGLONG
|
||||
#endif
|
||||
|
||||
template<class CharT>
|
||||
struct my_traits : std::char_traits<CharT>
|
||||
{
|
||||
};
|
||||
|
||||
template<class CharT>
|
||||
struct my_allocator : std::allocator<CharT>
|
||||
{
|
||||
};
|
||||
|
||||
// Test all 65536 values if true:
|
||||
bool const lcast_test_small_integral_types_completely = false;
|
||||
|
||||
// lcast_integral_test_counter: use when testing all values of an integral
|
||||
// types is not possible. Max. portable value is 32767.
|
||||
int const lcast_integral_test_counter=1000;
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void test_conversion_to_char();
|
||||
@@ -40,8 +68,26 @@ 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();
|
||||
void test_conversion_from_to_short();
|
||||
void test_conversion_from_to_ushort();
|
||||
void test_conversion_from_to_int();
|
||||
void test_conversion_from_to_uint();
|
||||
void test_conversion_from_to_long();
|
||||
void test_conversion_from_to_ulong();
|
||||
#ifdef LCAST_TEST_LONGLONG
|
||||
void test_conversion_from_to_longlong();
|
||||
void test_conversion_from_to_ulonglong();
|
||||
#endif
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
void test_traits();
|
||||
void test_wtraits();
|
||||
void test_allocator();
|
||||
void test_wallocator();
|
||||
#endif
|
||||
|
||||
unit_test_framework::test_suite *init_unit_test_suite(int, char **)
|
||||
unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||
{
|
||||
unit_test_framework::test_suite *suite =
|
||||
BOOST_TEST_SUITE("lexical_cast unit test");
|
||||
@@ -58,6 +104,25 @@ unit_test_framework::test_suite *init_unit_test_suite(int, char **)
|
||||
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));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_short));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ushort));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_int));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uint));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long));
|
||||
#ifdef LCAST_TEST_LONGLONG
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_longlong));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong));
|
||||
#endif
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
suite->add(BOOST_TEST_CASE(&test_traits));
|
||||
suite->add(BOOST_TEST_CASE(&test_wtraits));
|
||||
suite->add(BOOST_TEST_CASE(&test_allocator));
|
||||
suite->add(BOOST_TEST_CASE(&test_wallocator));
|
||||
#endif
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
@@ -67,110 +132,115 @@ void test_conversion_to_char()
|
||||
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), boost::bad_lexical_cast);
|
||||
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>(""), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<char>("Test"), boost::bad_lexical_cast);
|
||||
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("")), boost::bad_lexical_cast);
|
||||
lexical_cast<char>(std::string("")), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<char>(std::string("Test")), boost::bad_lexical_cast);
|
||||
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'),boost::bad_lexical_cast);
|
||||
BOOST_CHECK_EQUAL(1,lexical_cast<int>(1));
|
||||
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(1, lexical_cast<int>(1.0));
|
||||
|
||||
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), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_EQUAL(
|
||||
(std::numeric_limits<int>::min)(),
|
||||
lexical_cast<int>((std::numeric_limits<int>::min)()));
|
||||
|
||||
BOOST_CHECK_THROW(lexical_cast<int>(1e20), boost::bad_lexical_cast);
|
||||
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"), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<int>(""), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<int>("Test"), boost::bad_lexical_cast);
|
||||
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_EQUAL(123, lexical_cast<int>(std::string("123")));
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<int>(std::string(" 123")), boost::bad_lexical_cast);
|
||||
lexical_cast<int>(std::string(" 123")), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<int>(std::string("")), boost::bad_lexical_cast);
|
||||
lexical_cast<int>(std::string("")), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<int>(std::string("Test")), boost::bad_lexical_cast);
|
||||
lexical_cast<int>(std::string("Test")), bad_lexical_cast);
|
||||
}
|
||||
|
||||
void test_conversion_to_double()
|
||||
{
|
||||
BOOST_CHECK_EQUAL(1.0, lexical_cast<double>('1'));
|
||||
BOOST_CHECK_THROW(lexical_cast<double>('A'), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_EQUAL(1.0, lexical_cast<double>(1));
|
||||
BOOST_CHECK_EQUAL(1.23, lexical_cast<double>(1.23));
|
||||
BOOST_CHECK_CLOSE(
|
||||
(std::numeric_limits<double>::max)() / 2,
|
||||
lexical_cast<double>((std::numeric_limits<double>::max)() / 2),
|
||||
std::numeric_limits<double>::epsilon());
|
||||
BOOST_CHECK_EQUAL(1.0, lexical_cast<double>(true));
|
||||
BOOST_CHECK_EQUAL(0.0, lexical_cast<double>(false));
|
||||
BOOST_CHECK_EQUAL(1.23, lexical_cast<double>("1.23"));
|
||||
BOOST_CHECK_THROW(lexical_cast<double>(""), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<double>("Test"), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_EQUAL(1.23, lexical_cast<double>(std::string("1.23")));
|
||||
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("")), boost::bad_lexical_cast);
|
||||
lexical_cast<double>(std::string("")), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<double>(std::string("Test")), boost::bad_lexical_cast);
|
||||
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'), boost::bad_lexical_cast);
|
||||
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), boost::bad_lexical_cast);
|
||||
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>(""), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<bool>("Test"), boost::bad_lexical_cast);
|
||||
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("")), boost::bad_lexical_cast);
|
||||
lexical_cast<bool>(std::string("")), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<bool>(std::string("Test")), boost::bad_lexical_cast);
|
||||
lexical_cast<bool>(std::string("Test")), bad_lexical_cast);
|
||||
}
|
||||
|
||||
void test_conversion_to_string()
|
||||
{
|
||||
char buf[] = "hello";
|
||||
char* str = buf;
|
||||
BOOST_CHECK_EQUAL(str, lexical_cast<std::string>(str));
|
||||
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("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>(""));
|
||||
@@ -192,45 +262,53 @@ void test_conversion_from_to_wchar_t_alias()
|
||||
|
||||
void test_conversion_to_pointer()
|
||||
{
|
||||
BOOST_CHECK_THROW(lexical_cast<char *>("Test"), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<char *>("Test"), bad_lexical_cast);
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
BOOST_CHECK_THROW(lexical_cast<wchar_t *>("Test"), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<wchar_t *>("Test"), bad_lexical_cast);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_conversion_from_wchar_t()
|
||||
{
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#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'), boost::bad_lexical_cast);
|
||||
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""), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<int>(L"Test"), boost::bad_lexical_cast);
|
||||
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'), boost::bad_lexical_cast);
|
||||
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""), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<double>(L"Test"), boost::bad_lexical_cast);
|
||||
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'), boost::bad_lexical_cast);
|
||||
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""), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<bool>(L"Test"), boost::bad_lexical_cast);
|
||||
#endif
|
||||
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()
|
||||
{
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
#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), boost::bad_lexical_cast);
|
||||
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));
|
||||
@@ -239,14 +317,14 @@ void test_conversion_to_wchar_t()
|
||||
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""), boost::bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<wchar_t>(L"Test"), boost::bad_lexical_cast);
|
||||
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"")), boost::bad_lexical_cast);
|
||||
lexical_cast<wchar_t>(std::wstring(L"")), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<wchar_t>(std::wstring(L"Test")), boost::bad_lexical_cast);
|
||||
lexical_cast<wchar_t>(std::wstring(L"Test")), bad_lexical_cast);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -255,29 +333,35 @@ 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"")), boost::bad_lexical_cast);
|
||||
lexical_cast<int>(std::wstring(L"")), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<int>(std::wstring(L"Test")), boost::bad_lexical_cast);
|
||||
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"")), boost::bad_lexical_cast);
|
||||
lexical_cast<bool>(std::wstring(L"")), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(
|
||||
lexical_cast<bool>(std::wstring(L"Test")), boost::bad_lexical_cast);
|
||||
lexical_cast<bool>(std::wstring(L"Test")), bad_lexical_cast);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_conversion_to_wstring()
|
||||
{
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
wchar_t buf[] = L"hello";
|
||||
wchar_t* str = buf;
|
||||
BOOST_CHECK(str == lexical_cast<std::wstring>(str));
|
||||
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' '));
|
||||
BOOST_CHECK(L"A" == lexical_cast<std::wstring>('A'));
|
||||
#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""));
|
||||
@@ -286,3 +370,382 @@ void test_conversion_to_wstring()
|
||||
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);
|
||||
}
|
||||
|
||||
// Replace "-,999" with "-999".
|
||||
template<class CharT>
|
||||
std::basic_string<CharT> to_str_gcc_workaround(std::basic_string<CharT> str)
|
||||
{
|
||||
std::locale loc;
|
||||
std::numpunct<CharT> const& np = BOOST_USE_FACET(std::numpunct<CharT>, loc);
|
||||
std::ctype<CharT> const& ct = BOOST_USE_FACET(std::ctype<CharT>, loc);
|
||||
|
||||
if(np.grouping().empty())
|
||||
return str;
|
||||
|
||||
CharT prefix[3] = { ct.widen('-'), np.thousands_sep(), CharT() };
|
||||
|
||||
if(str.find(prefix) != 0)
|
||||
return str;
|
||||
|
||||
prefix[1] = CharT();
|
||||
str.replace(0, 2, prefix);
|
||||
return str;
|
||||
}
|
||||
|
||||
template<class CharT, class T>
|
||||
std::basic_string<CharT> to_str(T t)
|
||||
{
|
||||
std::basic_ostringstream<CharT> o;
|
||||
o << t;
|
||||
return to_str_gcc_workaround(o.str());
|
||||
}
|
||||
|
||||
template<class T, class CharT>
|
||||
void test_conversion_from_integral_to_char(CharT zero)
|
||||
{
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(0)) == zero + 0);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(1)) == zero + 1);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(2)) == zero + 2);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(3)) == zero + 3);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(4)) == zero + 4);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(5)) == zero + 5);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(6)) == zero + 6);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(7)) == zero + 7);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(8)) == zero + 8);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(9)) == zero + 9);
|
||||
|
||||
BOOST_CHECK_THROW(lexical_cast<CharT>(static_cast<T>(10)), bad_lexical_cast);
|
||||
|
||||
T t = (std::numeric_limits<T>::max)();
|
||||
BOOST_CHECK_THROW(lexical_cast<CharT>(t), bad_lexical_cast);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_conversion_from_integral_to_integral()
|
||||
{
|
||||
T t = 0;
|
||||
BOOST_CHECK(lexical_cast<T>(t) == t);
|
||||
|
||||
// Next two variables are used to supress warnings.
|
||||
int st = 32767; unsigned int ut = st;
|
||||
t = st;
|
||||
BOOST_CHECK(lexical_cast<short>(t) == st);
|
||||
BOOST_CHECK(lexical_cast<unsigned short>(t) == ut);
|
||||
BOOST_CHECK(lexical_cast<int>(t) == st);
|
||||
BOOST_CHECK(lexical_cast<unsigned int>(t) == ut);
|
||||
BOOST_CHECK(lexical_cast<long>(t) == st);
|
||||
BOOST_CHECK(lexical_cast<unsigned long>(t) == ut);
|
||||
|
||||
t = (std::numeric_limits<T>::max)();
|
||||
BOOST_CHECK(lexical_cast<T>(t) == t);
|
||||
|
||||
t = (std::numeric_limits<T>::min)();
|
||||
BOOST_CHECK(lexical_cast<T>(t) == t);
|
||||
}
|
||||
|
||||
template<class T, class CharT>
|
||||
void test_conversion_from_integral_to_string(CharT)
|
||||
{
|
||||
typedef std::numeric_limits<T> limits;
|
||||
typedef std::basic_string<CharT> string_type;
|
||||
|
||||
T t;
|
||||
|
||||
t = (limits::min)();
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
|
||||
t = (limits::max)();
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
|
||||
if(limits::digits <= 16 && lcast_test_small_integral_types_completely)
|
||||
// min and max have already been tested.
|
||||
for(t = 1 + (limits::min)(); t != (limits::max)(); ++t)
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
else
|
||||
{
|
||||
T const min_val = (limits::min)();
|
||||
T const max_val = (limits::max)();
|
||||
T const half_max_val = max_val / 2;
|
||||
T const cnt = lcast_integral_test_counter; // to supress warnings
|
||||
unsigned int const counter = cnt < half_max_val ? cnt : half_max_val;
|
||||
|
||||
unsigned int i;
|
||||
|
||||
// Test values around min:
|
||||
t = min_val;
|
||||
for(i = 0; i < counter; ++i, ++t)
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
|
||||
// Test values around max:
|
||||
t = max_val;
|
||||
for(i = 0; i < counter; ++i, --t)
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
|
||||
// Test values around zero:
|
||||
if(limits::is_signed)
|
||||
for(t = -counter; t < static_cast<T>(counter); ++t)
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
|
||||
// Test values around 100, 1000, 10000, ...
|
||||
T ten_power = 100;
|
||||
for(int e = 2; e <= limits::digits10; ++e, ten_power *= 10)
|
||||
{
|
||||
// ten_power + 100 probably never overflows
|
||||
for(t = ten_power - 100; t != ten_power + 100; ++t)
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, class CharT>
|
||||
void test_conversion_from_string_to_integral(CharT)
|
||||
{
|
||||
typedef std::numeric_limits<T> limits;
|
||||
|
||||
T t;
|
||||
|
||||
t = (limits::min)();
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
|
||||
t = (limits::max)();
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
|
||||
if(limits::digits <= 16 && lcast_test_small_integral_types_completely)
|
||||
// min and max have already been tested.
|
||||
for(t = 1 + (limits::min)(); t != (limits::max)(); ++t)
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
else
|
||||
{
|
||||
T const min_val = (limits::min)();
|
||||
T const max_val = (limits::max)();
|
||||
T const half_max_val = max_val / 2;
|
||||
T const cnt = lcast_integral_test_counter; // to supress warnings
|
||||
unsigned int const counter = cnt < half_max_val ? cnt : half_max_val;
|
||||
|
||||
unsigned int i;
|
||||
|
||||
// Test values around min:
|
||||
t = min_val;
|
||||
for(i = 0; i < counter; ++i, ++t)
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
|
||||
// Test values around max:
|
||||
t = max_val;
|
||||
for(i = 0; i < counter; ++i, --t)
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
|
||||
// Test values around zero:
|
||||
if(limits::is_signed)
|
||||
for(t = -counter; t < static_cast<T>(counter); ++t)
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
|
||||
// Test values around 100, 1000, 10000, ...
|
||||
T ten_power = 100;
|
||||
for(int e = 2; e <= limits::digits10; ++e, ten_power *= 10)
|
||||
{
|
||||
// ten_power + 100 probably never overflows
|
||||
for(t = ten_power - 100; t != ten_power + 100; ++t)
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_conversion_from_to_integral_for_locale()
|
||||
{
|
||||
test_conversion_from_integral_to_integral<T>();
|
||||
test_conversion_from_integral_to_string<T>('0');
|
||||
test_conversion_from_string_to_integral<T>('0');
|
||||
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
test_conversion_from_integral_to_string<T>(L'0');
|
||||
test_conversion_from_string_to_integral<T>(L'0');
|
||||
#endif
|
||||
}
|
||||
|
||||
struct restore_oldloc
|
||||
{
|
||||
std::locale oldloc;
|
||||
~restore_oldloc() { std::locale::global(oldloc); }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
void test_conversion_from_to_integral()
|
||||
{
|
||||
char const zero = '0';
|
||||
signed char const szero = '0';
|
||||
unsigned char const uzero = '0';
|
||||
test_conversion_from_integral_to_char<T>(zero);
|
||||
test_conversion_from_integral_to_char<T>(szero);
|
||||
test_conversion_from_integral_to_char<T>(uzero);
|
||||
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
wchar_t const wzero = L'0';
|
||||
test_conversion_from_integral_to_char<T>(wzero);
|
||||
#endif
|
||||
|
||||
// test_conversion_from_to_integral_for_locale
|
||||
|
||||
typedef std::numpunct<char> numpunct;
|
||||
|
||||
restore_oldloc guard;
|
||||
std::locale const& oldloc = guard.oldloc;
|
||||
|
||||
std::string grouping1 = BOOST_USE_FACET(numpunct, oldloc).grouping();
|
||||
std::string grouping2(grouping1);
|
||||
|
||||
test_conversion_from_to_integral_for_locale<T>();
|
||||
|
||||
try
|
||||
{
|
||||
std::locale newloc("");
|
||||
std::locale::global(newloc);
|
||||
|
||||
grouping2 = BOOST_USE_FACET(numpunct, newloc).grouping();
|
||||
}
|
||||
catch(std::exception const& ex)
|
||||
{
|
||||
std::string msg("Failed to set system locale: ");
|
||||
msg += ex.what();
|
||||
BOOST_TEST_MESSAGE(msg);
|
||||
}
|
||||
|
||||
if(grouping1 != grouping2)
|
||||
test_conversion_from_to_integral_for_locale<T>();
|
||||
|
||||
if(grouping1.empty() && grouping2.empty())
|
||||
BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested");
|
||||
}
|
||||
|
||||
void test_conversion_from_to_short()
|
||||
{
|
||||
test_conversion_from_to_integral<short>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_ushort()
|
||||
{
|
||||
test_conversion_from_to_integral<unsigned short>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_int()
|
||||
{
|
||||
test_conversion_from_to_integral<int>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_uint()
|
||||
{
|
||||
test_conversion_from_to_integral<unsigned int>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_ulong()
|
||||
{
|
||||
test_conversion_from_to_integral<unsigned long>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_long()
|
||||
{
|
||||
test_conversion_from_to_integral<long>();
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_LONG_LONG)
|
||||
|
||||
void test_conversion_from_to_longlong()
|
||||
{
|
||||
test_conversion_from_to_integral<boost::long_long_type>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_ulonglong()
|
||||
{
|
||||
test_conversion_from_to_integral<boost::ulong_long_type>();
|
||||
}
|
||||
|
||||
#elif defined(LCAST_TEST_LONGLONG)
|
||||
|
||||
void test_conversion_from_to_longlong()
|
||||
{
|
||||
test_conversion_from_to_integral<__int64>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_ulonglong()
|
||||
{
|
||||
test_conversion_from_to_integral<unsigned __int64>();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
void test_traits()
|
||||
{
|
||||
typedef std::basic_string<char, my_traits<char> > my_string;
|
||||
|
||||
my_string const s("s");
|
||||
BOOST_CHECK(boost::lexical_cast<char>(s) == s[0]);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(s) == s);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(-1) == "-1");
|
||||
}
|
||||
|
||||
void test_wtraits()
|
||||
{
|
||||
typedef std::basic_string<wchar_t, my_traits<wchar_t> > my_string;
|
||||
|
||||
my_string const s(L"s");
|
||||
BOOST_CHECK(boost::lexical_cast<wchar_t>(s) == s[0]);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(s) == s);
|
||||
//BOOST_CHECK(boost::lexical_cast<my_string>(-1) == L"-1");
|
||||
// Commented out because gcc 3.3 doesn't support this:
|
||||
// basic_ostream<wchar_t, my_traits<wchar_t> > o; o << -1;
|
||||
}
|
||||
|
||||
void test_allocator()
|
||||
{
|
||||
typedef std::basic_string< char
|
||||
, std::char_traits<char>
|
||||
, my_allocator<char>
|
||||
> my_string;
|
||||
|
||||
my_string s("s");
|
||||
BOOST_CHECK(boost::lexical_cast<char>(s) == s[0]);
|
||||
BOOST_CHECK(boost::lexical_cast<std::string>(s) == "s");
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(s) == s);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(1) == "1");
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>("s") == s);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(std::string("s")) == s);
|
||||
}
|
||||
|
||||
void test_wallocator()
|
||||
{
|
||||
typedef std::basic_string< wchar_t
|
||||
, std::char_traits<wchar_t>
|
||||
, my_allocator<wchar_t>
|
||||
> my_string;
|
||||
|
||||
my_string s(L"s");
|
||||
BOOST_CHECK(boost::lexical_cast<wchar_t>(s) == s[0]);
|
||||
BOOST_CHECK(boost::lexical_cast<std::wstring>(s) == L"s");
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(s) == s);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(1) == L"1");
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(L"s") == s);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(std::wstring(L"s")) == s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,34 +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/
|
||||
|
||||
|
||||
# Testing Jamfile autogenerated from XML source
|
||||
subproject libs/conversion/test ;
|
||||
|
||||
# bring in rules for testing
|
||||
import testing ;
|
||||
|
||||
# Make tests run by default.
|
||||
DEPENDS all : test ;
|
||||
|
||||
{
|
||||
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 ]
|
||||
;
|
||||
}
|
||||
|
||||
+6
-2
@@ -19,7 +19,11 @@ test-suite conversion
|
||||
: [ run implicit_cast.cpp ]
|
||||
[ compile-fail implicit_cast_fail.cpp ]
|
||||
[ run ../cast_test.cpp ]
|
||||
[ run ../lexical_cast_test.cpp ]
|
||||
[ run ../numeric_cast_test.cpp ]
|
||||
[ run ../lexical_cast_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
[ run lexical_cast_loopback_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
[ run lexical_cast_abstract_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
[ run lexical_cast_noncopyable_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/implicit_cast.hpp>
|
||||
#include <cassert>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/type.hpp>
|
||||
|
||||
using boost::implicit_cast;
|
||||
using boost::type;
|
||||
|
||||
@@ -25,9 +24,9 @@ typedef type<foo> foo_type;
|
||||
int main()
|
||||
{
|
||||
type<long> x = check_return(boost::implicit_cast<long>(1));
|
||||
assert(boost::implicit_cast<long>(1) == 1L);
|
||||
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 0;
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// Unit test for boost::lexical_cast.
|
||||
//
|
||||
// See http://www.boost.org for most recent version, including documentation.
|
||||
//
|
||||
// Copyright Sergey Shandar 2005, Alexander Nasonov, 2007.
|
||||
//
|
||||
// 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).
|
||||
//
|
||||
// Test abstract class. Bug 1358600:
|
||||
// http://sf.net/tracker/?func=detail&aid=1358600&group_id=7586&atid=107586
|
||||
|
||||
#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>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void test_abstract();
|
||||
|
||||
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_abstract));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
virtual void out(std::ostream &) const = 0;
|
||||
};
|
||||
|
||||
class B: public A
|
||||
{
|
||||
public:
|
||||
virtual void out(std::ostream &O) const { O << "B"; }
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &O, const A &a)
|
||||
{
|
||||
a.out(O);
|
||||
return O;
|
||||
};
|
||||
|
||||
void test_abstract()
|
||||
{
|
||||
const A &a = B();
|
||||
BOOST_CHECK(boost::lexical_cast<std::string>(a) == "B");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
// Unit test for boost::lexical_cast.
|
||||
//
|
||||
// See http://www.boost.org for most recent version, including documentation.
|
||||
//
|
||||
// Copyright Alexander Nasonov, 2006.
|
||||
//
|
||||
// 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).
|
||||
//
|
||||
// Test round-tripping conversion FPT -> string -> FPT,
|
||||
// where FPT is Floating Point Type.
|
||||
|
||||
#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>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void test_round_conversion_float();
|
||||
void test_round_conversion_double();
|
||||
void test_round_conversion_long_double();
|
||||
|
||||
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_round_conversion_float));
|
||||
suite->add(BOOST_TEST_CASE(&test_round_conversion_double));
|
||||
suite->add(BOOST_TEST_CASE(&test_round_conversion_long_double));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_round_conversion()
|
||||
{
|
||||
T epsilon = std::numeric_limits<T>::epsilon();
|
||||
std::string const epsilon_s = boost::lexical_cast<std::string>(epsilon);
|
||||
BOOST_CHECK(epsilon == lexical_cast<T>(epsilon_s));
|
||||
|
||||
T max_ = (std::numeric_limits<T>::max)();
|
||||
std::string const max_s = boost::lexical_cast<std::string>(max_);
|
||||
BOOST_CHECK(max_ == lexical_cast<T>(max_s));
|
||||
|
||||
T min_ = (std::numeric_limits<T>::min)();
|
||||
std::string const min_s = boost::lexical_cast<std::string>(min_);
|
||||
BOOST_CHECK(min_ == lexical_cast<T>(min_s));
|
||||
|
||||
T max_div137 = max_ / 137;
|
||||
std::string max_div137_s = boost::lexical_cast<std::string>(max_div137);
|
||||
BOOST_CHECK(max_div137 == lexical_cast<T>(max_div137_s));
|
||||
|
||||
T epsilon_mult137 = epsilon * 137;
|
||||
std::string epsilon_mult137_s(lexical_cast<std::string>(epsilon_mult137));
|
||||
BOOST_CHECK(epsilon_mult137 == lexical_cast<T>(epsilon_mult137_s));
|
||||
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
// See bug http://tinyurl.com/vhpvo
|
||||
template<class T>
|
||||
void test_msvc_magic_values()
|
||||
{
|
||||
T magic_msvc = 0.00010000433948393407;
|
||||
std::string magic_msvc_s = boost::lexical_cast<std::string>(magic_msvc);
|
||||
BOOST_CHECK(magic_msvc == lexical_cast<T>(magic_msvc_s));
|
||||
}
|
||||
#endif
|
||||
|
||||
void test_round_conversion_float()
|
||||
{
|
||||
test_round_conversion<float>();
|
||||
}
|
||||
|
||||
void test_round_conversion_double()
|
||||
{
|
||||
test_round_conversion<double>();
|
||||
#if defined(BOOST_MSVC)
|
||||
test_msvc_magic_values<double>();
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_round_conversion_long_double()
|
||||
{
|
||||
test_round_conversion<long double>();
|
||||
#if defined(BOOST_MSVC)
|
||||
test_msvc_magic_values<long double>();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// Unit test for boost::lexical_cast.
|
||||
//
|
||||
// See http://www.boost.org for most recent version, including documentation.
|
||||
//
|
||||
// Copyright Alexander Nasonov, 2007.
|
||||
//
|
||||
// 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).
|
||||
//
|
||||
// Test that Source can be non-copyable.
|
||||
|
||||
#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/noncopyable.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void test_noncopyable();
|
||||
|
||||
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_noncopyable));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
class Noncopyable : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
Noncopyable() {}
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &out, const Noncopyable&)
|
||||
{
|
||||
return out << "Noncopyable";
|
||||
}
|
||||
|
||||
void test_noncopyable()
|
||||
{
|
||||
Noncopyable x;
|
||||
BOOST_CHECK(boost::lexical_cast<std::string>(x) == "Noncopyable");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user