Compare commits

..

2 Commits

Author SHA1 Message Date
nobody c35f326490 This commit was manufactured by cvs2svn to create tag
'Version_1_28_0'.

[SVN r13949]
2002-05-16 13:26:18 +00:00
nobody 175c00ea3e This commit was manufactured by cvs2svn to create branch 'RC_1_28_0'.
[SVN r13795]
2002-05-10 04:34:27 +00:00
5 changed files with 416 additions and 712 deletions
+40 -85
View File
@@ -6,7 +6,7 @@
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org/libs/conversion for Documentation.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 02 Apr 01 Removed BOOST_NO_LIMITS workarounds and included
@@ -48,7 +48,6 @@
# 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
@@ -126,77 +125,54 @@ namespace boost
namespace detail
{
template <class T>
struct signed_numeric_limits : std::numeric_limits<T>
{
static inline T min()
template <bool is_signed> struct numeric_min_select;
template<>
struct numeric_min_select<true>
{
template <class T>
struct limits : std::numeric_limits<T>
{
return std::numeric_limits<T>::min() >= 0
static inline T min()
# ifndef __GNUC__ // bug workaround courtesy Jens Maurer
{
return std::numeric_limits<T>::min() >= 0
// unary minus causes integral promotion, thus the static_cast<>
? static_cast<T>(-std::numeric_limits<T>::max())
: std::numeric_limits<T>::min();
}
# else
;
# endif
};
};
# ifdef __GNUC__ // bug workaround courtesy Jens Maurer
template<> template<class T>
inline T numeric_min_select<true>::limits<T>::min()
{
return std::numeric_limits<T>::min() >= 0
// unary minus causes integral promotion, thus the static_cast<>
? static_cast<T>(-std::numeric_limits<T>::max())
: std::numeric_limits<T>::min();
}
# endif
template<>
struct numeric_min_select<false>
{
template <class T>
struct limits : std::numeric_limits<T> {};
};
// Move to namespace boost in utility.hpp?
template <class T, bool specialized>
struct fixed_numeric_limits_base
: public if_true< std::numeric_limits<T>::is_signed >
::BOOST_NESTED_TEMPLATE then< signed_numeric_limits<T>,
std::numeric_limits<T>
>::type
{};
// Move to namespace boost in utility.hpp?
template <class T>
struct fixed_numeric_limits
: fixed_numeric_limits_base<T,(std::numeric_limits<T>::is_specialized)>
{};
# ifdef BOOST_HAS_LONG_LONG
// cover implementations which supply no specialization for long
// long / unsigned long long. Not intended to be full
// numeric_limits replacements, but good enough for numeric_cast<>
template <>
struct fixed_numeric_limits_base<long long, false>
: public numeric_min_select<
std::numeric_limits<T>::is_signed
>::template limits<T>
{
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
BOOST_STATIC_CONSTANT(bool, is_signed = true);
static long long max()
{
# ifdef LONGLONG_MAX
return LONGLONG_MAX;
# else
return 9223372036854775807LL; // hope this is portable
# endif
}
static long long min()
{
# ifdef LONGLONG_MIN
return LONGLONG_MIN;
# else
return -9223372036854775808LL; // hope this is portable
# endif
}
};
template <>
struct fixed_numeric_limits_base<unsigned long long, false>
{
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
BOOST_STATIC_CONSTANT(bool, is_signed = false);
static unsigned long long max()
{
# ifdef ULONGLONG_MAX
return ULONGLONG_MAX;
# else
return 0xffffffffffffffffULL; // hope this is portable
# endif
}
static unsigned long long min() { return 0; }
};
# endif
} // namespace detail
// less_than_type_min -
@@ -260,24 +236,6 @@ namespace boost
template <class X, class Y>
static inline bool check(X x, Y)
{ return x >= 0 && static_cast<X>(static_cast<Y>(x)) != x; }
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200
// MSVC6 can't static_cast unsigned __int64 -> floating types
# define BOOST_UINT64_CAST(src_type) \
static inline bool check(src_type x, unsigned __int64) \
{ \
if (x < 0) return false; \
unsigned __int64 y = static_cast<unsigned __int64>(x); \
bool odd = y & 0x1; \
__int64 div2 = static_cast<__int64>(y >> 1); \
return ((static_cast<src_type>(div2) * 2.0) + odd) != x; \
}
BOOST_UINT64_CAST(long double);
BOOST_UINT64_CAST(double);
BOOST_UINT64_CAST(float);
# undef BOOST_UINT64_CAST
# endif
};
template<>
@@ -334,13 +292,10 @@ namespace boost
inline Target numeric_cast(Source arg BOOST_EXPLICIT_DEFAULT_TARGET)
{
// typedefs abbreviating respective trait classes
typedef detail::fixed_numeric_limits<Source> arg_traits;
typedef std::numeric_limits<Source> arg_traits;
typedef detail::fixed_numeric_limits<Target> result_traits;
#if defined(BOOST_STRICT_CONFIG) \
|| (!defined(__HP_aCC) || __HP_aCC > 33900) \
&& (!defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) \
|| defined(BOOST_SGI_CPP_LIMITS))
#if !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)
+35 -164
View File
@@ -1,38 +1,31 @@
// boost lexical_cast.hpp header -------------------------------------------//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_LEXICAL_CAST_INCLUDED
#define BOOST_LEXICAL_CAST_INCLUDED
// Boost lexical_cast.hpp header -------------------------------------------//
//
// See http://www.boost.org for most recent version including documentation.
// See end of this header for rights and permissions.
//
// what: lexical_cast custom keyword cast
// who: contributed by Kevlin Henney,
// enhanced with contributions from Terje Slettebø,
// with additional fixes and suggestions from Gennaro Prota,
// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
// and other Boosters
// when: November 2000, March 2003
// who: contributed by Kevlin Henney, with alternative naming, behaviors
// and fixes contributed by Dave Abrahams, Daryle Walker and other
// Boosters on the list
// when: November 2000
// where: tested with MSVC 6.0, BCC 5.5, and g++ 2.91
#include <string>
#include <typeinfo>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_pointer.hpp>
#ifdef BOOST_NO_STRINGSTREAM
#include <strstream>
// Some sstream implementations are broken for the purposes of lexical cast.
# if defined(BOOST_NO_STRINGSTREAM)
# define BOOST_LEXICAL_CAST_USE_STRSTREAM
# endif
#ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
# include <strstream>
#else
#include <sstream>
# include <sstream>
#endif
#if defined(BOOST_NO_STRINGSTREAM) || \
defined(BOOST_NO_STD_WSTRING) || \
defined(BOOST_NO_STD_LOCALE) || \
defined(BOOST_NO_INTRINSIC_WCHAR_T)
#define DISABLE_WIDE_CHAR_SUPPORT
#endif
#include <typeinfo>
namespace boost
{
@@ -40,159 +33,35 @@ namespace boost
class bad_lexical_cast : public std::bad_cast
{
public:
bad_lexical_cast() :
source(&typeid(void)), target(&typeid(void))
{
}
bad_lexical_cast(
const std::type_info &s,
const std::type_info &t) :
source(&s), target(&t)
{
}
const std::type_info &source_type() const
{
return *source;
}
const std::type_info &target_type() const
{
return *target;
}
virtual const char *what() const throw()
// constructors, destructors, and assignment operator defaulted
// function inlined for brevity and consistency with rest of library
virtual const char * what() const throw()
{
return "bad lexical cast: "
"source type value could not be interpreted as target";
}
virtual ~bad_lexical_cast() throw()
{
}
private:
const std::type_info *source;
const std::type_info *target;
};
namespace detail // selectors for choosing stream character type
{
template<typename Type>
struct stream_char
{
typedef char type;
};
#ifndef DISABLE_WIDE_CHAR_SUPPORT
template<>
struct stream_char<wchar_t>
{
typedef wchar_t type;
};
template<>
struct stream_char<wchar_t *>
{
typedef wchar_t type;
};
template<>
struct stream_char<const wchar_t *>
{
typedef wchar_t type;
};
template<>
struct stream_char<std::wstring>
{
typedef wchar_t type;
};
#endif
template<typename TargetChar, typename SourceChar>
struct widest_char
{
typedef TargetChar type;
};
template<>
struct widest_char<char, wchar_t>
{
typedef wchar_t type;
};
}
namespace detail // stream wrapper for handling lexical conversions
{
template<typename Target, typename Source>
class lexical_stream
{
public:
lexical_stream()
{
stream.unsetf(std::ios::skipws);
if(std::numeric_limits<Target>::is_specialized)
stream.precision(std::numeric_limits<Target>::digits10 + 1);
else if(std::numeric_limits<Source>::is_specialized)
stream.precision(std::numeric_limits<Source>::digits10 + 1);
}
~lexical_stream()
{
#if defined(BOOST_NO_STRINGSTREAM)
stream.freeze(false);
#endif
}
bool operator<<(const Source &input)
{
return !(stream << input).fail();
}
template<typename InputStreamable>
bool operator>>(InputStreamable &output)
{
return !is_pointer<InputStreamable>::value &&
stream >> output &&
(stream >> std::ws).eof();
}
bool operator>>(std::string &output)
{
#if defined(BOOST_NO_STRINGSTREAM)
stream << '\0';
#endif
output = stream.str();
return true;
}
#ifndef DISABLE_WIDE_CHAR_SUPPORT
bool operator>>(std::wstring &output)
{
output = stream.str();
return true;
}
#endif
private:
typedef typename widest_char<
typename stream_char<Target>::type,
typename stream_char<Source>::type>::type char_type;
#if defined(BOOST_NO_STRINGSTREAM)
std::strstream stream;
#elif defined(BOOST_NO_STD_LOCALE)
std::stringstream stream;
#else
std::basic_stringstream<char_type> stream;
#endif
};
}
template<typename Target, typename Source>
Target lexical_cast(Source arg)
{
detail::lexical_stream<Target, Source> interpreter;
# ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
std::strstream interpreter; // for out-of-the-box g++ 2.95.2
# else
std::stringstream interpreter;
# endif
Target result;
if(!(interpreter << arg && interpreter >> result))
throw_exception(bad_lexical_cast(typeid(Target), typeid(Source)));
if(!(interpreter << arg) || !(interpreter >> result) ||
!(interpreter >> std::ws).eof())
throw bad_lexical_cast();
return result;
}
}
// Copyright Kevlin Henney, 2000-2003. All rights reserved.
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
@@ -200,6 +69,8 @@ namespace boost
//
// This software is provided "as is" without express or implied warranty.
#undef DISABLE_WIDE_CHAR_SUPPORT
#ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
# undef BOOST_LEXICAL_CAST_USE_STRSTREAM
#endif
#endif
+196 -177
View File
@@ -1,95 +1,94 @@
<!-- 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 4.0">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Header
<a href="../../boost/lexical_cast.hpp">boost/lexical_cast.hpp</a></h1>
<ul 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="cast.htm#numeric_cast">numeric_cast</a></code>
may offer more reasonable behavior than <code>lexical_cast</code>.
<p>
For a good discussion of the options and issues involved in string-based
formatting, including comparison of <code>stringstream</code>, <code>lexical_cast</code>,
and others, see Herb Sutter's article, <a href="http://www.gotw.ca/publications/mill19.htm">
<i>The String Formatters of Manor Farm</i></a>.
<p>
<hr>
<h2><a name="examples">Examples</a></h2>
The following example treats command line arguments as a sequence of numeric
data: <blockquote>
<pre>
<head>
<title>lexical_cast</title>
<meta name="author" content="Kevlin Henney, mailto:kevlin@curbralan.com">
<meta name="generator" content="Microsoft FrontPage 4.0">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Header
<a href="../../boost/lexical_cast.hpp">boost/lexical_cast.hpp</a></h1>
<ul>
<li><a href="#motivation">Motivation</a></li>
<li><a href="#examples">Examples</a></li>
<li><a href="#synopsis">Synopsis</a></li>
<li><a href="#lexical_cast"><code>lexical_cast</code></a></li>
<li><a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a></li>
<li><a href="#portability">Portability</a></li>
<li><a href="#future">Future directions</a></li>
</ul>
<hr>
<h2><a name="motivation">Motivation</a></h2>
Sometimes a value must be converted to a literal text form, such as an
<code>int</code> represented as a <code>string</code>, or vice-versa, when
a <code>string</code> is interpreted as an <code>int</code>. Such examples
are common when converting between data types internal to a program and
representation external to a program, such as windows and configuration files.
<p>
The standard C and C++ libraries offer a number of facilities for performing
such conversions. However, they vary with their ease of use, extensibility,
and safety.
<p>
For instance, there are a number of limitations with the family of standard C
functions typified by <code>atoi</code>:
<ul>
<li>
Conversion is supported in one direction only: from text to
internal data type. Converting the other way using the C library
requires either the inconvenience and compromised safety of the
<code>sprintf</code> function, or the loss of portability associated
with non-standard functions such as <code>itoa</code>.
</li>
<li>
The range of types supported is only a subset of the built-in numeric
types, namely <code>int</code>, <code>long</code>,
and <code>double</code>.
</li>
<li>
The range of types cannot be extended in a uniform manner. For
instance, conversion from string representation to
<code>complex</code> or <code>rational</code>.
</li>
</ul>
The standard C functions typified by <code>strtol</code> have the same basic
limitations, but offer finer control over the conversion process. However, for
the common case such control is often either not required or not used. The
<code>scanf</code> family of functions offer even greater control, but also
lack safety and ease of use.
<p>
The standard C++ library offers <code>stringstream</code> for the kind of
in-core formatting being discussed. It offers a great deal of control over the
formatting and conversion of I/O to and from arbitrary types through text.
However, for simple conversions direct use of <code>stringstream</code> can be
either clumsy (with the introduction of extra local variables and the loss of
infix-expression convenience) or obscure (where <code>stringstream</code>
objects are created as temporary objects in an expression). Facets provide a
comprehensive concept and facility for controlling textual representation, but
their relatively high entry level requires an extreme degree of involvement
for simple conversions.
<p>
The <code>lexical_cast</code> template function offers a convenient and consistent
form for supporting common conversions to and from arbitrary types when they are
represented as text. The simplification it offers is in expression-level
convenience for such conversions. For more involved conversions, such as where
precision or formatting need tighter control than is offered by the default
behavior of <code>lexical_cast</code>, the conventional
<code>stringstream</code> approach is recommended. Where the conversions are
numeric to numeric, <code><a href="cast.htm#numeric_cast">numeric_cast</a></code> may offer more reasonable
behavior than <code>lexical_cast</code>.
<p>
<hr>
<h2><a name="examples">Examples</a></h2>
The following example treats command line arguments as a sequence of numeric data:
<blockquote>
<pre>
int main(int argc, char * argv[])
{
using boost::lexical_cast;
@@ -111,8 +110,11 @@ int main(int argc, char * argv[])
...
}
</pre>
</blockquote>The following example uses numeric data in a string expression: <blockquote>
<pre>
</blockquote>
The following example uses numeric data in a string expression:
<blockquote>
<pre>
void log_message(const std::string &amp;);
void log_errno(int yoko)
@@ -120,12 +122,15 @@ void log_errno(int yoko)
log_message(&quot;Error &quot; + boost::lexical_cast&lt;std::string&gt;(yoko) + &quot;: &quot; + strerror(yoko));
}
</pre>
</blockquote>
<hr>
<h2><a name="synopsis">Synopsis</a></h2>
Library features defined in <a href="../../boost/lexical_cast.hpp"><code>&quot;boost/lexical_cast.hpp&quot;</code></a>:
<blockquote>
<pre>
</blockquote>
<hr>
<h2><a name="synopsis">Synopsis</a></h2>
Library features defined in <a href="../../boost/lexical_cast.hpp"><code>&quot;boost/lexical_cast.hpp&quot;</code></a>:
<blockquote>
<pre>
namespace boost
{
class <a href="#bad_lexical_cast">bad_lexical_cast</a>;
@@ -133,91 +138,105 @@ namespace boost
Target <a href="#lexical_cast">lexical_cast</a>(Source arg);
}
</pre>
</blockquote>Unit test defined in <a href="lexical_cast_test.cpp"><code>&quot;lexical_cast_test.cpp&quot;</code></a>.
<p>
<hr>
<h2><a name="lexical_cast"><code>lexical_cast</code></a></h2>
<blockquote>
<pre>
</blockquote>
Test harness defined in <a href="lexical_cast_test.cpp"><code>&quot;lexical_cast_test.cpp&quot;</code></a>.
<p>
<hr>
<h2><a name="lexical_cast"><code>lexical_cast</code></a></h2>
<blockquote>
<pre>
template&lt;typename Target, typename Source&gt;
Target lexical_cast(Source arg);
</pre>
</blockquote>Returns the result of streaming <code>arg</code> into a
standard library string-based stream and then out as a <code>Target</code> object.
Where <code>Target</code> is either <code>std::string</code>
or <code>std::wstring</code>, stream extraction takes the whole content
of the string, including spaces, rather than relying on the default
<code>operator&gt;&gt;</code> behavior.
If the conversion is unsuccessful, a <a href="#bad_lexical_cast">
<code>bad_lexical_cast</code></a> exception is thrown.
<p>
The requirements on the argument and result types are:
<ul type="square">
<li>
<code>Source</code> is <i>OutputStreamable</i>, meaning that an <code>operator&lt;&lt;</code>
is defined that takes a <code>std::ostream</code> or <code>std::wostream</code> object on the
left hand side and an instance of the argument type on the right.
</li>
<li>
<code>Target</code> is <i>InputStreamable</i>, meaning that an <code>operator&gt;&gt;</code>
is defined that takes a <code>std::istream</code> or <code>std::wistream</code> object on the left hand side
and an instance of the result type on the right.
</li>
<li>
Both <code>Source</code> and <code>Target</code> are <i>CopyConstructible</i> [20.1.3].
</li>
<li>
<code>Target</code> is <i>DefaultConstructible</i>, meaning that it is possible
to <i>default-initialize</i> an object of that type [8.5, 20.1.4].
</li>
</ul>
The character type of the underlying stream is assumed to be <code>char</code> unless
either the <code>Source</code> or the <code>Target</code> requires wide-character
streaming, in which case the underlying stream uses <code>wchar_t</code>.
<code>Source</code> types that require wide-character streaming are <code>wchar_t</code>,
<code>wchar_t *</code>, and <code>std::wstring</code>. <code>Target</code> types that
require wide-character streaming are <code>wchar_t</code> and <code>std::wstring</code>.
<p>
Where a higher degree of control is required over conversions, <code>std::stringstream</code>
and <code>std::wstringstream</code> offer a more appropriate path. Where non-stream-based conversions are
required, <code>lexical_cast</code>
is the wrong tool for the job and is not special-cased for such scenarios.
<p>
<hr>
<h2><a name="bad_lexical_cast"><code>bad_lexical_cast</code></a></h2>
<blockquote>
<pre>
</blockquote>
Returns the result of streaming <code>arg</code> into a <code>std::stringstream</code> and then
out as a <code>Target</code> object. The conversion is parameterized by the current
<a href="#lexical_context"><code>lexical_context</code></a>, if set. If the conversion is
unsuccessful, a <a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a> exception is thrown
if the current <a href="#lexical_context"><code>lexical_context</code></a> is set for throwing or
if there is no current <a href="#lexical_context"><code>lexical_context</code></a> set, otherwise a
<code>Target()</code> is returned.
<p>
The requirements on the argument and result types are:
<ul>
<li>
<code>Source</code> is <i>OutputStreamable</i>, meaning that an
<code>operator&lt;&lt;</code> is defined that takes a
<code>std::ostream</code> object on the left hand side and an instance
of the argument type on the right.
</li>
<li>
Both <code>Source</code> and <code>Target</code> are <i>CopyConstructible</i> [20.1.3].
</li>
<li>
<code>Target</code> is <i>InputStreamable</i>, meaning that an
<code>operator&gt;&gt;</code> is defined that takes a
<code>std::istream</code> object on the left hand side and an instance
of the result type on the right.
</li>
<li>
<code>Target</code> is <i>DefaultConstructible</i>, meaning that it is
possible to <i>default-initialize</i> an object of that type [8.5, 20.1.3].
</li>
<li>
<code>Target</code> is <i>Assignable</i> [23.1].
</li>
</ul>
<p>
<hr>
<h2><a name="bad_lexical_cast"><code>bad_lexical_cast</code></a></h2>
<blockquote>
<pre>
class bad_lexical_cast : public std::bad_cast
{
public:
... // <i>same member function interface as</i> std::exception
virtual const char * what() const throw();
};
</pre>
</blockquote>Exception used to indicate runtime <a href="#lexical_cast"><code>lexical_cast</code></a>
failure.
<hr>
<h2><a name="changes">Changes</a></h2>
<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&lt;std::string&gt;("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&lt;char *&gt;("Goodbye, World")</code> now throws an exception instead of
causing undefined behavior.
</ul>
<p>
<hr>
<div align="right"><small><i>&copy; Copyright Kevlin Henney, 2000&#150;2003</i></small></div>
</body>
</blockquote>
Exception used to indicate runtime <a href="#lexical_cast"><code>lexical_cast</code></a> failure.
<p>
<hr>
<h2><a name="portability">Portability</a></h2>
To date the code and test harness have been compiled successfully using
Microsoft Visual C++ 6.0, Borland C++ 5.5, and GNU g++ 2.91. Tests have run successfully for
Microsoft Visual C++ 6.0 and Borland C++ 5.5. For g++ streams interpret any integer, rather than
just <code>0</code> and <code>1</code>, as valid for <code>bool</code>; the other tests pass
without problem. The deprecated standard header <code>&lt;strstream&gt;</code> is used in
preference to the standard <code>&lt;sstream&gt;</code> header for out-of-the-box g++ support.
<p>
<hr>
<h2><a name="future">Future directions</a></h2>
<ul>
<li>
A mechanism for providing quality-of-service control is needed, e.g. formatting and exception
behavior. In the name of simplicity (and release), the current version strips out an earlier
experimental version.
</li>
<li>
Wide character and incompatible <code>std::basic_string</code> issues need to be catered for.
</li>
<li>
An <code>interpret_cast</code> that performs a <i>do-something-reasonable</i> conversion between
types. It would, for instance, select between <code>numeric_cast</code> and <code>lexical_cast</code>
based on <code>std::numeric_limits<>::is_specialized</code>.
</li>
</ul>
<hr>
<div align="right"><small><i>&copy; Copyright Kevlin Henney, 2000</i></small></div>
</body>
</html>
+144 -285
View File
@@ -1,290 +1,149 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Terje Slettebø and Kevlin Henney, 2003.
// boost lexical_cast_test.cpp program -------------------------------------//
// See http://www.boost.org for most recent version including documentation.
// what: lexical_cast custom keyword cast tests
// who: contributed by Kevlin Henney
// when: October 2000
// where: tested with MSVC 6.0 and BCC 5.5
#include <boost/lexical_cast.hpp>
#include "test.hpp"
#include <complex>
#include <iostream>
#include <string>
using namespace boost;
using namespace std;
typedef test::test<const char *, void (*)()> test_case;
typedef const test_case * test_case_iterator;
extern const test_case_iterator begin, end;
int main()
{
test::tester<test_case_iterator> test_suite(begin, end);
return test_suite() ? EXIT_SUCCESS : EXIT_FAILURE;
}
void test_to_string()
{
test::check_equal(
lexical_cast<string>(2001), "2001",
"2001 -> \"2001\"");
test::check_equal(
lexical_cast<string>(2001.0), "2001",
"2001.0 ->\"2001\"");
test::check_equal(
lexical_cast<string>(complex<double>(2000,1)), "(2000,1)",
"complex<double>(2000,1) -> \"(2000,1)\"");
}
void test_to_int()
{
test::check_equal(
lexical_cast<int>("2001"), 2001,
"\"2001\" -> 2001");
test::check_equal(
lexical_cast<int>(" 2001"), 2001,
"\" 2001\" -> 2001");
test::check_equal(
lexical_cast<int>("2001 "), 2001,
"\"2001 \" -> 2001");
TEST_CHECK_THROW(
lexical_cast<int>("Two thousand and one"),
bad_lexical_cast,
"\"Two thousand and one\"");
TEST_CHECK_THROW(
lexical_cast<int>("2001: A Space Odyssey"),
bad_lexical_cast,
"\"2001: A Space Odyssey\"");
TEST_CHECK_THROW(
lexical_cast<int>(200.1),
bad_lexical_cast,
"200.1");
TEST_CHECK_THROW(
lexical_cast<int>("200e1"),
bad_lexical_cast,
"\"200e1\"");
}
void test_to_char()
{
test::check_equal(
lexical_cast<char>("2"), '2',
"\"2\" -> '2'");
test::check_equal(
lexical_cast<char>(" 2"), '2',
"\" 2\" -> '2'");
test::check_equal(
lexical_cast<char>("2 "), '2',
"\"2 \" -> '2'");
test::check_equal(
lexical_cast<char>(2), '2',
"2 -> '2'");
TEST_CHECK_THROW(
lexical_cast<char>("2001"),
bad_lexical_cast,
"\"2001\"");
TEST_CHECK_THROW(
lexical_cast<char>(2001),
bad_lexical_cast,
"2001");
}
void test_to_double()
{
test::check_equal(
lexical_cast<double>("1e6"), 1e6,
"\"1e6\" -> 1e6");
test::check_equal(
lexical_cast<double>("1e-2"), 1e-2,
"\"1e-2\" -> 1e-2");
}
void test_to_bool()
{
test::check_equal(
lexical_cast<bool>(1), true,
"1 -> true");
test::check_equal(
lexical_cast<bool>('0'), false,
"'0' -> false");
TEST_CHECK_THROW(
lexical_cast<bool>(2001),
bad_lexical_cast,
"2001");
TEST_CHECK_THROW(
lexical_cast<bool>(2),
bad_lexical_cast,
"2");
TEST_CHECK_THROW(
lexical_cast<bool>("true thousand and one"),
bad_lexical_cast,
"\"true thousand and one\"");
}
const test_case test_cases[] =
{
{ "lexical_cast<std::string>", test_to_string },
{ "lexical_cast<int>", test_to_int },
{ "lexical_cast<char>", test_to_char },
{ "lexical_cast<double>", test_to_double },
{ "lexical_cast<bool>", test_to_bool }
};
const test_case_iterator begin = test_cases;
const test_case_iterator end =
test_cases + (sizeof test_cases / sizeof *test_cases);
// Copyright Kevlin Henney, 2000. All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
// permissions notice appear in all copies and derivatives, and that no
// charge may be made for the software and its documentation except to cover
// cost of distribution.
//
// This software is provided "as is" without express or implied warranty.
#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/floating_point_comparison.hpp>
#include <boost/test/included/unit_test_framework.hpp>
#if defined(BOOST_NO_STRINGSTREAM) || \
defined(BOOST_NO_STD_WSTRING) || \
defined(BOOST_NO_STD_LOCALE) || \
defined(BOOST_NO_INTRINSIC_WCHAR_T)
#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();
unit_test_framework::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
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), boost::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_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);
BOOST_CHECK_THROW(
lexical_cast<char>(std::string("Test")), boost::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(
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_THROW(lexical_cast<int>(1e20), boost::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);
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")), boost::bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<int>(std::string("")), boost::bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<int>(std::string("Test")), boost::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_THROW(
lexical_cast<double>(std::string("")), boost::bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<double>(std::string("Test")), boost::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_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_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_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);
BOOST_CHECK_THROW(
lexical_cast<bool>(std::string("Test")), boost::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"), boost::bad_lexical_cast);
#ifndef DISABLE_WIDE_CHAR_SUPPORT
BOOST_CHECK_THROW(lexical_cast<wchar_t *>("Test"), boost::bad_lexical_cast);
#endif
}
void test_conversion_from_wchar_t()
{
#ifndef DISABLE_WIDE_CHAR_SUPPORT
BOOST_CHECK_EQUAL(1, lexical_cast<int>(L'1'));
BOOST_CHECK_THROW(lexical_cast<int>(L'A'), boost::bad_lexical_cast);
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_EQUAL(1.0, lexical_cast<double>(L'1'));
BOOST_CHECK_THROW(lexical_cast<double>(L'A'), boost::bad_lexical_cast);
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_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_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
}
void test_conversion_to_wchar_t()
{
#ifndef DISABLE_WIDE_CHAR_SUPPORT
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.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""), boost::bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<wchar_t>(L"Test"), boost::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);
BOOST_CHECK_THROW(
lexical_cast<wchar_t>(std::wstring(L"Test")), boost::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"")), boost::bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<int>(std::wstring(L"Test")), boost::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);
BOOST_CHECK_THROW(
lexical_cast<bool>(std::wstring(L"Test")), boost::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));
BOOST_CHECK(L"A" == lexical_cast<std::wstring>(L'A'));
BOOST_CHECK(L" " == lexical_cast<std::wstring>(L' '));
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
}
+1 -1
View File
@@ -44,7 +44,7 @@ namespace test // failure exception used to indicate checked test failures
}
// std::~string has no exception-specification (could throw anything),
// but we need to be compatible with std::~exception's empty one
// but we need to be compatible with std::~exception's empty one
// see std::15.4p13 and std::15.4p3
~failure() throw()
{