mirror of
https://github.com/boostorg/conversion.git
synced 2025-08-03 22:44:32 +02:00
update from Kevlin and Terje
[SVN r17861]
This commit is contained in:
@@ -1,31 +1,29 @@
|
|||||||
// boost lexical_cast.hpp header -------------------------------------------//
|
|
||||||
|
|
||||||
// See http://www.boost.org/libs/conversion for documentation.
|
|
||||||
|
|
||||||
#ifndef BOOST_LEXICAL_CAST_INCLUDED
|
#ifndef BOOST_LEXICAL_CAST_INCLUDED
|
||||||
#define BOOST_LEXICAL_CAST_INCLUDED
|
#define BOOST_LEXICAL_CAST_INCLUDED
|
||||||
|
|
||||||
|
// boost lexical_cast.hpp header --------------------------------------------//
|
||||||
|
|
||||||
|
// See http://www.boost.org/libs/conversion for documentation.
|
||||||
|
// See end of this header for rights and permissions.
|
||||||
|
//
|
||||||
// what: lexical_cast custom keyword cast
|
// what: lexical_cast custom keyword cast
|
||||||
// who: contributed by Kevlin Henney, with alternative naming, behaviors
|
// who: contributed by Kevlin Henney,
|
||||||
// and fixes contributed by Dave Abrahams, Daryle Walker and other
|
// enhanced with contributions from Terje Sletteb<65>,
|
||||||
// Boosters on the list
|
// with additional fixes and suggestions from Gennaro Prota,
|
||||||
// when: November 2000
|
// Dave Abrahams, Daryle Walker, and other Boosters on the list
|
||||||
// where: tested with MSVC 6.0, BCC 5.5, and g++ 2.91
|
// when: November 2000, March 2003
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
|
|
||||||
// Some sstream implementations are broken for the purposes of lexical cast.
|
|
||||||
# if defined(BOOST_NO_STRINGSTREAM)
|
|
||||||
# define BOOST_LEXICAL_CAST_USE_STRSTREAM
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
|
|
||||||
# include <strstream>
|
|
||||||
#else
|
|
||||||
# include <sstream>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/limits.hpp>
|
||||||
|
#include <boost/type_traits.hpp>
|
||||||
|
|
||||||
|
#ifdef BOOST_NO_STRINGSTREAM
|
||||||
|
#include <strstream>
|
||||||
|
#else
|
||||||
|
#include <sstream>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
@@ -33,35 +31,146 @@ namespace boost
|
|||||||
class bad_lexical_cast : public std::bad_cast
|
class bad_lexical_cast : public std::bad_cast
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// constructors, destructors, and assignment operator defaulted
|
virtual ~bad_lexical_cast() throw()
|
||||||
|
|
||||||
// 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";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail // actual underlying concrete exception type
|
||||||
|
{
|
||||||
|
template<typename Target, typename Source>
|
||||||
|
class no_lexical_conversion : public bad_lexical_cast
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
no_lexical_conversion()
|
||||||
|
: description(
|
||||||
|
std::string() + "bad lexical cast: " +
|
||||||
|
"source type value could not be interpreted as target, Target=" +
|
||||||
|
typeid(Target).name() + ", Source=" + typeid(Source).name())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual ~no_lexical_conversion() throw()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual const char *what() const throw()
|
||||||
|
{
|
||||||
|
return description.c_str();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const std::string description; // static initialization fails on MSVC6
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail // selectors for choosing stream character type
|
||||||
|
{
|
||||||
|
template<typename Type>
|
||||||
|
struct stream_char
|
||||||
|
{
|
||||||
|
typedef char type;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef BOOST_NO_STRINGSTREAM
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
template<typename InputStreamable>
|
||||||
|
bool operator>>(InputStreamable &output)
|
||||||
|
{
|
||||||
|
return !is_pointer<InputStreamable>::value &&
|
||||||
|
stream >> output &&
|
||||||
|
(stream >> std::ws).eof();
|
||||||
|
}
|
||||||
|
template<typename Char, typename Traits, typename Allocator>
|
||||||
|
bool operator>>(std::basic_string<Char, Traits, Allocator> &output)
|
||||||
|
{
|
||||||
|
return std::getline(stream, output, char_type()).eof();
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
#else
|
||||||
|
std::basic_stringstream<char_type> stream;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Target, typename Source>
|
template<typename Target, typename Source>
|
||||||
Target lexical_cast(Source arg)
|
Target lexical_cast(Source arg)
|
||||||
{
|
{
|
||||||
# ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
|
detail::lexical_stream<Target, Source> interpreter;
|
||||||
std::strstream interpreter; // for out-of-the-box g++ 2.95.2
|
|
||||||
# else
|
|
||||||
std::stringstream interpreter;
|
|
||||||
# endif
|
|
||||||
Target result;
|
Target result;
|
||||||
|
|
||||||
if(!(interpreter << arg) || !(interpreter >> result) ||
|
if(!(interpreter << arg && interpreter >> result))
|
||||||
!(interpreter >> std::ws).eof())
|
throw detail::no_lexical_conversion<Target, Source>();
|
||||||
throw bad_lexical_cast();
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
|
// Copyright Kevlin Henney, 2000-2003. All rights reserved.
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose is hereby granted without fee, provided that this copyright and
|
// purpose is hereby granted without fee, provided that this copyright and
|
||||||
@@ -69,8 +178,4 @@ namespace boost
|
|||||||
//
|
//
|
||||||
// This software is provided "as is" without express or implied warranty.
|
// This software is provided "as is" without express or implied warranty.
|
||||||
|
|
||||||
#ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
|
|
||||||
# undef BOOST_LEXICAL_CAST_USE_STRSTREAM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
356
lexical_cast.htm
356
lexical_cast.htm
@@ -1,99 +1,94 @@
|
|||||||
<!doctype html public "-//W3C//DTD HTML Transitional 4.0//EN">
|
<!doctype html public "-//W3C//DTD HTML Transitional 4.0//EN">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>lexical_cast</title>
|
<title>lexical_cast</title>
|
||||||
<meta name="author" content="Kevlin Henney, mailto:kevlin@curbralan.com">
|
<meta name="author" content="Kevlin Henney, mailto:kevlin@curbralan.com">
|
||||||
<meta name="generator" content="Microsoft FrontPage 4.0">
|
<meta name="generator" content="Microsoft FrontPage 4.0">
|
||||||
</head>
|
</head>
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
<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>
|
||||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Header
|
<ul>
|
||||||
<a href="../../boost/lexical_cast.hpp">boost/lexical_cast.hpp</a></h1>
|
<li>
|
||||||
|
<a href="#motivation">Motivation</a></li>
|
||||||
<ul>
|
<li>
|
||||||
<li><a href="#motivation">Motivation</a></li>
|
<a href="#examples">Examples</a></li>
|
||||||
<li><a href="#examples">Examples</a></li>
|
<li>
|
||||||
<li><a href="#synopsis">Synopsis</a></li>
|
<a href="#synopsis">Synopsis</a></li>
|
||||||
<li><a href="#lexical_cast"><code>lexical_cast</code></a></li>
|
<li>
|
||||||
<li><a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a></li>
|
<a href="#lexical_cast"><code>lexical_cast</code></a></li>
|
||||||
<li><a href="#portability">Portability</a></li>
|
<li>
|
||||||
<li><a href="#future">Future directions</a></li>
|
<a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<hr>
|
||||||
<hr>
|
<h2><a name="motivation">Motivation</a></h2>
|
||||||
<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>
|
||||||
Sometimes a value must be converted to a literal text form, such as an
|
is interpreted as an <code>int</code>. Such examples are common when converting
|
||||||
<code>int</code> represented as a <code>string</code>, or vice-versa, when
|
between data types internal to a program and representation external to a
|
||||||
a <code>string</code> is interpreted as an <code>int</code>. Such examples
|
program, such as windows and configuration files.
|
||||||
are common when converting between data types internal to a program and
|
<p>
|
||||||
representation external to a program, such as windows and configuration files.
|
The standard C and C++ libraries offer a number of facilities for performing
|
||||||
<p>
|
such conversions. However, they vary with their ease of use, extensibility, and
|
||||||
The standard C and C++ libraries offer a number of facilities for performing
|
safety.
|
||||||
such conversions. However, they vary with their ease of use, extensibility,
|
<p>
|
||||||
and safety.
|
For instance, there are a number of limitations with the family of standard C
|
||||||
<p>
|
functions typified by <code>atoi</code>:
|
||||||
For instance, there are a number of limitations with the family of standard C
|
<ul>
|
||||||
functions typified by <code>atoi</code>:
|
<li>
|
||||||
<ul>
|
Conversion is supported in one direction only: from text to internal data type.
|
||||||
<li>
|
Converting the other way using the C library requires either the inconvenience
|
||||||
Conversion is supported in one direction only: from text to
|
and compromised safety of the <code>sprintf</code> function, or the loss of
|
||||||
internal data type. Converting the other way using the C library
|
portability associated with non-standard functions such as <code>itoa</code>.
|
||||||
requires either the inconvenience and compromised safety of the
|
</li>
|
||||||
<code>sprintf</code> function, or the loss of portability associated
|
<li>
|
||||||
with non-standard functions such as <code>itoa</code>.
|
The range of types supported is only a subset of the built-in numeric types,
|
||||||
</li>
|
namely <code>int</code>, <code>long</code>, and <code>double</code>.
|
||||||
<li>
|
</li>
|
||||||
The range of types supported is only a subset of the built-in numeric
|
<li>
|
||||||
types, namely <code>int</code>, <code>long</code>,
|
The range of types cannot be extended in a uniform manner. For instance,
|
||||||
and <code>double</code>.
|
conversion from string representation to <code>complex</code> or <code>rational</code>.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
</ul>
|
||||||
The range of types cannot be extended in a uniform manner. For
|
The standard C functions typified by <code>strtol</code> have the same basic
|
||||||
instance, conversion from string representation to
|
limitations, but offer finer control over the conversion process. However, for
|
||||||
<code>complex</code> or <code>rational</code>.
|
the common case such control is often either not required or not used. The <code>scanf</code>
|
||||||
</li>
|
family of functions offer even greater control, but also lack safety and ease
|
||||||
</ul>
|
of use.
|
||||||
The standard C functions typified by <code>strtol</code> have the same basic
|
<p>
|
||||||
limitations, but offer finer control over the conversion process. However, for
|
The standard C++ library offers <code>stringstream</code> for the kind of
|
||||||
the common case such control is often either not required or not used. The
|
in-core formatting being discussed. It offers a great deal of control over the
|
||||||
<code>scanf</code> family of functions offer even greater control, but also
|
formatting and conversion of I/O to and from arbitrary types through text.
|
||||||
lack safety and ease of use.
|
However, for simple conversions direct use of <code>stringstream</code> can be
|
||||||
<p>
|
either clumsy (with the introduction of extra local variables and the loss of
|
||||||
The standard C++ library offers <code>stringstream</code> for the kind of
|
infix-expression convenience) or obscure (where <code>stringstream</code>
|
||||||
in-core formatting being discussed. It offers a great deal of control over the
|
objects are created as temporary objects in an expression). Facets provide a
|
||||||
formatting and conversion of I/O to and from arbitrary types through text.
|
comprehensive concept and facility for controlling textual representation, but
|
||||||
However, for simple conversions direct use of <code>stringstream</code> can be
|
their perceived complexity and high entry level requires an extreme degree of
|
||||||
either clumsy (with the introduction of extra local variables and the loss of
|
involvement for simple conversions, and excludes all but a few programmers.
|
||||||
infix-expression convenience) or obscure (where <code>stringstream</code>
|
<p>
|
||||||
objects are created as temporary objects in an expression). Facets provide a
|
The <code>lexical_cast</code> function template offers a convenient and
|
||||||
comprehensive concept and facility for controlling textual representation, but
|
consistent form for supporting common conversions to and from arbitrary types
|
||||||
their relatively high entry level requires an extreme degree of involvement
|
when they are represented as text. The simplification it offers is in
|
||||||
for simple conversions.
|
expression-level convenience for such conversions. For more involved
|
||||||
<p>
|
conversions, such as where precision or formatting need tighter control than is
|
||||||
The <code>lexical_cast</code> template function offers a convenient and consistent
|
offered by the default behavior of <code>lexical_cast</code>, the conventional <code>
|
||||||
form for supporting common conversions to and from arbitrary types when they are
|
stringstream</code> approach is recommended. Where the conversions are
|
||||||
represented as text. The simplification it offers is in expression-level
|
numeric to numeric, <code><a href="cast.htm#numeric_cast">numeric_cast</a></code>
|
||||||
convenience for such conversions. For more involved conversions, such as where
|
may offer more reasonable behavior than <code>lexical_cast</code>
|
||||||
precision or formatting need tighter control than is offered by the default
|
.
|
||||||
behavior of <code>lexical_cast</code>, the conventional
|
<p>
|
||||||
<code>stringstream</code> approach is recommended. Where the conversions are
|
For a good discussion of the options and issues involved in string-based
|
||||||
numeric to numeric, <code><a href="cast.htm#numeric_cast">numeric_cast</a></code>
|
formatting, including comparison of <code>stringstream</code>, <code>lexical_cast</code>,
|
||||||
may offer more reasonable behavior than <code>lexical_cast</code>.
|
and others, see Herb Sutter's article, <a href="http://www.gotw.ca/publications/mill19.htm">
|
||||||
<p>
|
<i>The String Formatters of Manor Farm</i></a>
|
||||||
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
|
<p>
|
||||||
others, see Herb Sutter's article, <a href="http://www.gotw.ca/publications/mill19.htm">
|
<hr>
|
||||||
<i>The String Formatters of Manor Farm</i></a>.
|
<h2><a name="examples">Examples</a></h2>
|
||||||
<p>
|
The following example treats command line arguments as a sequence of numeric
|
||||||
|
data: <blockquote>
|
||||||
<hr>
|
<pre>
|
||||||
<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[])
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
using boost::lexical_cast;
|
using boost::lexical_cast;
|
||||||
@@ -115,11 +110,8 @@ int main(int argc, char * argv[])
|
|||||||
...
|
...
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>The following example uses numeric data in a string expression: <blockquote>
|
||||||
|
<pre>
|
||||||
The following example uses numeric data in a string expression:
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
void log_message(const std::string &);
|
void log_message(const std::string &);
|
||||||
|
|
||||||
void log_errno(int yoko)
|
void log_errno(int yoko)
|
||||||
@@ -127,15 +119,12 @@ void log_errno(int yoko)
|
|||||||
log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
|
log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
<hr>
|
||||||
<hr>
|
<h2><a name="synopsis">Synopsis</a></h2>
|
||||||
<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>
|
||||||
Library features defined in <a href="../../boost/lexical_cast.hpp"><code>"boost/lexical_cast.hpp"</code></a>:
|
<pre>
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
class <a href="#bad_lexical_cast">bad_lexical_cast</a>;
|
class <a href="#bad_lexical_cast">bad_lexical_cast</a>;
|
||||||
@@ -143,110 +132,65 @@ namespace boost
|
|||||||
Target <a href="#lexical_cast">lexical_cast</a>(Source arg);
|
Target <a href="#lexical_cast">lexical_cast</a>(Source arg);
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>Unit test defined in <a href="lexical_cast_test.cpp"><code>"lexical_cast_test.cpp"</code></a>.
|
||||||
|
<p>
|
||||||
Test harness defined in <a href="lexical_cast_test.cpp"><code>"lexical_cast_test.cpp"</code></a>.
|
<hr>
|
||||||
<p>
|
<h2><a name="lexical_cast"><code>lexical_cast</code></a></h2>
|
||||||
|
<blockquote>
|
||||||
<hr>
|
<pre>
|
||||||
<h2><a name="lexical_cast"><code>lexical_cast</code></a></h2>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
template<typename Target, typename Source>
|
template<typename Target, typename Source>
|
||||||
Target lexical_cast(Source arg);
|
Target lexical_cast(Source arg);
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>Returns the result of streaming <code>arg</code> into a <code>std::stringstream</code>
|
||||||
|
and then out as a <code>Target</code> object. Note that spaces are significant
|
||||||
Returns the result of streaming <code>arg</code> into a <code>std::stringstream</code> and then
|
in any conversion and are not skipped. If the conversion is unsuccessful, a <a href="#bad_lexical_cast">
|
||||||
out as a <code>Target</code> object. If the conversion is unsuccessful, a
|
<code>bad_lexical_cast</code></a>
|
||||||
<a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a> exception is thrown.
|
exception is thrown.
|
||||||
<p>
|
<p>
|
||||||
The requirements on the argument and result types are:
|
The requirements on the argument and result types are:
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<code>Source</code> is <i>OutputStreamable</i>, meaning that an
|
<code>Source</code> is <i>OutputStreamable</i>, meaning that an <code>operator<<</code>
|
||||||
<code>operator<<</code> is defined that takes a
|
is defined that takes a <code>std::ostream</code> or <code>std::wostream</code> object on the
|
||||||
<code>std::ostream</code> object on the left hand side and an instance
|
left hand side and an instance of the argument type on the right.
|
||||||
of the argument type on the right.
|
</li>
|
||||||
</li>
|
<li>
|
||||||
<li>
|
Both <code>Source</code> and <code>Target</code> are <i>CopyConstructible</i> [20.1.3].
|
||||||
Both <code>Source</code> and <code>Target</code> are <i>CopyConstructible</i> [20.1.3].
|
</li>
|
||||||
</li>
|
<li>
|
||||||
<li>
|
<code>Target</code> is <i>InputStreamable</i>, meaning that an <code>operator>></code>
|
||||||
<code>Target</code> is <i>InputStreamable</i>, meaning that an
|
is defined that takes a <code>std::istream</code> or <code>std::wistream</code> object on the left hand side
|
||||||
<code>operator>></code> is defined that takes a
|
and an instance of the result type on the right.
|
||||||
<code>std::istream</code> object on the left hand side and an instance
|
</li>
|
||||||
of the result type on the right.
|
<li>
|
||||||
</li>
|
<code>Target</code> is <i>DefaultConstructible</i>, meaning that it is possible
|
||||||
<li>
|
to <i>default-initialize</i> an object of that type [8.5, 20.1.4].
|
||||||
<code>Target</code> is <i>DefaultConstructible</i>, meaning that it is
|
</li>
|
||||||
possible to <i>default-initialize</i> an object of that type [8.5, 20.1.3].
|
</ul>
|
||||||
</li>
|
The character type of the underlying stream is assumed to be <code>char</code> unless
|
||||||
<li>
|
the either the <code>Source</code> or the <code>Target</code> type is <code>wchar_t</code>
|
||||||
<code>Target</code> is <i>Assignable</i> [23.1].
|
or a wide-character string type — either <code>wchar_t *</code> or <code>std::wstring</code> —
|
||||||
</li>
|
in which case <code>wchar_t</code> is used.
|
||||||
</ul>
|
<p>
|
||||||
<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
|
||||||
<hr>
|
required, <code>lexical_cast</code>
|
||||||
<h2><a name="bad_lexical_cast"><code>bad_lexical_cast</code></a></h2>
|
is the wrong tool for the job, and is not special-cased for such scenarios.
|
||||||
|
<p>
|
||||||
<blockquote>
|
<hr>
|
||||||
<pre>
|
<h2><a name="bad_lexical_cast"><code>bad_lexical_cast</code></a></h2>
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
class bad_lexical_cast : public std::bad_cast
|
class bad_lexical_cast : public std::bad_cast
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual const char * what() const throw();
|
... // <i>same member function interface as</i> std::exception
|
||||||
};
|
};
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>Exception used to indicate runtime <a href="#lexical_cast"><code>lexical_cast</code></a>
|
||||||
|
failure.
|
||||||
Exception used to indicate runtime <a href="#lexical_cast"><code>lexical_cast</code></a> failure.
|
<p>
|
||||||
<p>
|
<hr>
|
||||||
|
<div align="right"><small><i>© Copyright Kevlin Henney, 2000–2003</i></small></div>
|
||||||
<hr>
|
</body>
|
||||||
<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><strstream></code> is used in
|
|
||||||
preference to the standard <code><sstream></code> header for out-of-the-box g++ support.
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<h2><a name="future">Future directions</a></h2>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Improved string handling, correctly accommodating wide character strings, incompatible
|
|
||||||
<code>basic_string</code> types, and empty strings.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Optimize the use of a stream away for identity conversions.
|
|
||||||
</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>. This would be an interesting
|
|
||||||
project, but there are no concrete plans to pursue this at the moment.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
It is also worth mentioning future <i>non-directions</i>: anything that involves adding extra
|
|
||||||
arguments for a conversion operation is not being considered. A custom keyword cast, such as
|
|
||||||
<code>lexical_cast</code>, is intended to look like a built-in cast operator: built-in cast operators
|
|
||||||
take only a single operand. Where a higher degree of control is required over conversions, the
|
|
||||||
standard <code>stringstream</code> offers a more appropriate path. Where non-stream-based conversions
|
|
||||||
are required, <code>lexical_cast</code> is the wrong tool for the job, and so it won't be special-cased
|
|
||||||
for such scenarios.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<div align="right"><small><i>© Copyright Kevlin Henney, 2000, 2002</i></small></div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
@@ -1,149 +1,315 @@
|
|||||||
// boost lexical_cast_test.cpp program -------------------------------------//
|
// Unit test for boost::lexical_cast.
|
||||||
|
//
|
||||||
// See http://www.boost.org for most recent version including documentation.
|
// See http://www.boost.org for most recent version, including documentation.
|
||||||
|
//
|
||||||
// what: lexical_cast custom keyword cast tests
|
// Copyright Terje Sletteb<65> and Kevlin Henney, 2003.
|
||||||
// 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
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose is hereby granted without fee, provided that this copyright and
|
// purpose is hereby granted without fee, provided that this copyright and
|
||||||
// permissions notice appear in all copies and derivatives, and that no
|
// permissions notice appear in all copies and derivatives.
|
||||||
// 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.
|
// This software is provided "as is" without express or implied warranty.
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
|
#if defined(__INTEL_COMPILER)
|
||||||
|
#pragma warning(disable: 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 BOOST_NO_STRINGSTREAM is defined wide character support is unavailable,
|
||||||
|
// and all wide character tests are disabled.
|
||||||
|
|
||||||
|
#ifdef BOOST_NO_STRINGSTREAM
|
||||||
|
#define NO_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_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_to_pointer));
|
||||||
|
suite->add(BOOST_TEST_CASE(test_conversion_to_string));
|
||||||
|
#ifndef NO_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>("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_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>(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>("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_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>(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()
|
||||||
|
{
|
||||||
|
// *** All the following gives compilation error (ambiguity) on MSVC 6
|
||||||
|
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>("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_to_pointer()
|
||||||
|
{
|
||||||
|
BOOST_CHECK_THROW(lexical_cast<char *>("Test"), boost::bad_lexical_cast);
|
||||||
|
#ifndef NO_WIDE_CHAR_SUPPORT
|
||||||
|
BOOST_CHECK_THROW(lexical_cast<wchar_t *>("Test"), boost::bad_lexical_cast);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_conversion_from_wchar_t()
|
||||||
|
{
|
||||||
|
#ifndef NO_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(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(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);
|
||||||
|
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 NO_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>(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 NO_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(1.23, lexical_cast<double>(std::wstring(L"1.23")));
|
||||||
|
BOOST_CHECK_THROW(
|
||||||
|
lexical_cast<double>(std::wstring(L"")), boost::bad_lexical_cast);
|
||||||
|
BOOST_CHECK_THROW(
|
||||||
|
lexical_cast<double>(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 NO_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>(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
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user