Compare commits

..

2 Commits

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

[SVN r26264]
2004-11-19 19:19:18 +00:00
nobody dfca010fb3 This commit was manufactured by cvs2svn to create branch 'RC_1_32_0'.
[SVN r25797]
2004-10-20 08:26:43 +00:00
30 changed files with 826 additions and 6397 deletions
+105 -43
View File
@@ -3,7 +3,7 @@
<html>
<head>
<meta name="generator" content=
"Microsoft FrontPage 5.0">
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
<meta http-equiv="Content-Type" content=
"text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
@@ -19,9 +19,10 @@
<h2><a name="Cast Functions">Cast Functions</a></h2>
<p>The header <a href="../../boost/cast.hpp">boost/cast.hpp</a> provides <code>
<a href="#Polymorphic_cast">polymorphic_cast</a> and</code> <a href=
"#Polymorphic_cast"><code>polymorphic_downcast</code></a> function templates designed to
<p>The header <a href="../../boost/cast.hpp">boost/cast.hpp</a> provides
<a href="#Polymorphic_cast"><b>polymorphic_cast</b></a>, <a href=
"#Polymorphic_cast"><b>polymorphic_downcast</b></a>, and <a href=
"#numeric_cast"><b>numeric_cast</b></a> function templates designed to
complement the C++ built-in casts.</p>
<p>The program <a href="cast_test.cpp">cast_test.cpp</a> can be used to
@@ -33,50 +34,43 @@
least one virtual function) are sometimes downcast or crosscast.
Downcasting means casting from a base class to a derived class.
Crosscasting means casting across an inheritance hierarchy diagram, such
as from one base to the other in a <code>Y</code> diagram hierarchy.</p>
as from one base to the other in a <b>Y</b> diagram hierarchy.</p>
<p>Such casts can be done with old-style casts, but this approach is
never to be recommended. Old-style casts are sorely lacking in type
safety, suffer poor readability, and are difficult to locate with search
tools.</p>
<p>The C++ built-in <code>static_cast</code> can be used for efficiently
<p>The C++ built-in <b>static_cast</b> can be used for efficiently
downcasting pointers to polymorphic objects, but provides no error
detection for the case where the pointer being cast actually points to
the wrong derived class. The <code>polymorphic_downcast</code> template retains
the efficiency of <code>static_cast</code> for non-debug compilations, but for
debug compilations adds safety via an assert() that a <code>dynamic_cast</code>
the wrong derived class. The <b>polymorphic_downcast</b> template retains
the efficiency of <b>static_cast</b> for non-debug compilations, but for
debug compilations adds safety via an assert() that a <b>dynamic_cast</b>
succeeds.</p>
<p>The C++ built-in <code>dynamic_cast</code> can be used for downcasts and
<p>The C++ built-in <b>dynamic_cast</b> can be used for downcasts and
crosscasts of pointers to polymorphic objects, but error notification in
the form of a returned value of 0 is inconvenient to test, or worse yet,
easy to forget to test. The throwing form of <code>dynamic_cast</code>, which
easy to forget to test. The throwing form of <b>dynamic_cast</b>, which
works on references, can be used on pointers through the ugly expression
&amp;<code>dynamic_cast&lt;T&amp;&gt;(*p)</code>, which causes undefined
behavior if <code>p</code> is <code>0</code>. The <code>polymorphic_cast</code>
template performs a <code>dynamic_cast</code> on a pointer, and throws an
exception if the <code>dynamic_cast</code> returns 0.</p>
behavior if <code>p</code> is <code>0</code>. The <b>polymorphic_cast</b>
template performs a <b>dynamic_cast</b> on a pointer, and throws an
exception if the <b>dynamic_cast</b> returns 0.</p>
<p>A <code>polymorphic_downcast</code> should be used for
downcasts that you are certain should succeed. Error checking is
only performed in translation units where <code>NDEBUG</code> is
not defined, via
<pre> assert( dynamic_cast&lt;Derived&gt;(x) == x )
</pre> where <code>x</code> is the source pointer. This approach
ensures that not only is a non-zero pointer returned, but also
that it is correct in the presence of multiple inheritance.
Attempts to crosscast using <code>polymorphic_downcast</code> will
fail to compile.
<b>Warning:</b> Because <code>polymorphic_downcast</code> uses assert(), it
violates the One Definition Rule (ODR) if NDEBUG is inconsistently
defined across translation units. [See ISO Std 3.2]
</p><p>
For crosscasts, or when the success of a cast can only be known at
runtime, or when efficiency is not important,
<code>polymorphic_cast</code> is preferred. </p>
<p>A <b>polymorphic_downcast</b> is preferred when debug-mode tests will
cover 100% of the object types possibly cast and when non-debug-mode
efficiency is an issue. If these two conditions are not present,
<b>polymorphic_cast</b> is preferred. It must also be used for
crosscasts. It does an assert( dynamic_cast&lt;Derived&gt;(x) == x )
where x is the base pointer, ensuring that not only is a non-zero pointer
returned, but also that it correct in the presence of multiple
inheritance. <b>Warning:</b>: Because <b>polymorphic_downcast</b> uses
assert(), it violates the one definition rule (ODR) if NDEBUG is
inconsistently defined across translation units. [See ISO Std 3.2]</p>
<p>The C++ built-in <code>dynamic_cast</code> must be used to cast references
<p>The C++ built-in <b>dynamic_cast</b> must be used to cast references
rather than pointers. It is also the only cast that can be used to check
whether a given interface is supported; in that case a return of 0 isn't
an error condition.</p>
@@ -84,7 +78,8 @@
<h3>polymorphic_cast and polymorphic_downcast synopsis</h3>
<blockquote>
<pre>namespace boost {
<pre>
namespace boost {
template &lt;class Derived, class Base&gt;
inline Derived polymorphic_cast(Base* x);
@@ -103,7 +98,8 @@ inline Derived polymorphic_downcast(Base* x);
<h3>polymorphic_downcast example</h3>
<blockquote>
<pre>#include &lt;boost/cast.hpp&gt;
<pre>
#include &lt;boost/cast.hpp&gt;
...
class Fruit { public: virtual ~Fruit(){}; ... };
class Banana : public Fruit { ... };
@@ -115,20 +111,85 @@ void f( Fruit * fruit ) {
</pre>
</blockquote>
<h3><a name="numeric_cast">numeric_cast</a></h3>
<p>A <b>static_cast</b> or implicit conversion will not detect failure to
preserve range for numeric casts. The <b>numeric_cast</b> function
templates are similar to <b>static_cast</b> and certain (dubious)
implicit conversions in this respect, except that they detect loss of
numeric range. An exception is thrown when a runtime value-preservation
check fails.</p>
<p>The requirements on the argument and result types are:</p>
<blockquote>
<ul>
<li>Both argument and result types are CopyConstructible [ISO Std
20.1.3].</li>
<li>Both argument and result types are Numeric, defined by
<code>std::numeric_limits&lt;&gt;::is_specialized</code> being
true.</li>
<li>The argument can be converted to the result type using
<b>static_cast</b>.</li>
</ul>
</blockquote>
<h3>numeric_cast synopsis</h3>
<blockquote>
<pre>
namespace boost {
class bad_numeric_cast : public std::bad_cast {...};
template&lt;typename Target, typename Source&gt;
inline Target numeric_cast(Source arg);
// Throws: bad_numeric_cast unless, in converting arg from Source to Target,
// there is no loss of negative range, and no underflow, and no
// overflow, as determined by std::numeric_limits
// Returns: static_cast&lt;Target&gt;(arg)
}
</pre>
</blockquote>
<h3>numeric_cast example</h3>
<blockquote>
<pre>
#include &lt;boost/cast.hpp&gt;
using namespace boost::cast;
void ariane(double vx)
{
...
unsigned short dx = numeric_cast&lt;unsigned short&gt;(vx);
...
}
</pre>
</blockquote>
<h3>numeric_cast rationale</h3>
<p>The form of the throws condition is specified so that != is not a
required operation.</p>
<h3>History</h3>
<p><code>polymorphic_cast</code> was suggested by Bjarne Stroustrup in "The C++
<p><b>polymorphic_cast</b> was suggested by Bjarne Stroustrup in "The C++
Programming Language".<br>
<code>polymorphic_downcast</code> was contributed by <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>.<code><br>
An old
numeric_cast</code> that was contributed by <a href=
"http://www.boost.org/people/kevlin_henney.htm">Kevlin Henney</a> is now superseeded by the <a href="../numeric/conversion/doc/html/index.html">Boost Numeric Conversion Library</a></p>
<b>polymorphic_downcast</b> was contributed by <a href=
"../../people/dave_abrahams.htm">Dave Abrahams</a>.<b><br>
numeric_cast</b> was contributed by <a href=
"../../people/kevlin_henney.htm">Kevlin Henney</a>.</p>
<hr>
<p>Revised
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
-->June 23, 2005<!--webbot bot="Timestamp" endspan i-checksum="30348"
-->06 January, 2001
<!--webbot bot="Timestamp" endspan i-checksum="38320"
--></p>
<p>&copy; Copyright boost.org 1999. Permission to copy, use, modify, sell
@@ -137,4 +198,5 @@ void f( Fruit * fruit ) {
or implied warranty, and with no claim as to its suitability for any
purpose.</p>
</body>
</html>
</html>
-16
View File
@@ -1,16 +0,0 @@
# Copyright Antony Polukhin 2011. Use, modification, and distribution are
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
using quickbook ;
import boostbook : boostbook ;
xml lexical_cast : lexical_cast.qbk ;
boostbook standalone
:
lexical_cast
:
<xsl:param>boost.root=../../../..
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;
-752
View File
@@ -1,752 +0,0 @@
[library Boost.Lexical_Cast
[quickbook 1.5]
[version 1.0]
[copyright 2000-2005 Kevlin Henney]
[copyright 2006-2010 Alexander Nasonov]
[copyright 2011-2012 Antony Polukhin]
[category String and text processing]
[category Miscellaneous]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
]
[def __numericcast__ [@boost:libs/numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html `boost::numeric_cast`]]
[def __proposallong__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1973.html Lexical Conversion Library Proposal for TR2, N1973 by Kevlin Henney and Beman Dawes]]
[def __proposalshort__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1973.html Lexical Conversion Library Proposal for TR2, N1973]]
[section Motivation]
Sometimes a value must be converted to a literal text form, such as an [c++] `int` represented as a `std::string`, or vice-versa, when a `std::string` is interpreted as an `int`. 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.
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.
For instance, there are a number of limitations with the family of standard C functions typified by `atoi`:
* 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 `sprintf` function, or the loss of portability associated with non-standard functions such as `itoa`.
* The range of types supported is only a subset of the built-in numeric types, namely `int`, `long`, and `double`.
* The range of types cannot be extended in a uniform manner. For instance, conversion from string representation to complex or rational.
The standard C functions typified by `strtol` 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 `scanf` family of functions offer even greater control, but also lack safety and ease of use.
The standard C++ library offers `stringstream` 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 `stringstream` can be either clumsy (with the introduction of extra local variables and the loss of infix-expression convenience) or obscure (where `stringstream` 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.
The `lexical_cast` 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 `lexical_cast`, the conventional `std::stringstream` approach is recommended. Where the conversions are numeric to numeric, __numericcast__ may offer more reasonable behavior than `lexical_cast`.
For a good discussion of the options and issues involved in string-based formatting, including comparison of `stringstream`, `lexical_cast`, and others, see Herb Sutter's article, [@http://www.gotw.ca/publications/mill19.htm The String Formatters of Manor Farm]. Also, take a look at the [link boost_lexical_cast.performance Performance] section.
[endsect]
[section Examples]
The following example treats command line arguments as a sequence of numeric data:
``
int main(int argc, char * argv[])
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
std::vector<short> args;
while(*++argv)
{
try
{
args.push_back(lexical_cast<short>(*argv));
}
catch(bad_lexical_cast &)
{
args.push_back(0);
}
}
...
}
``
The following example uses numeric data in a string expression:
``
void log_message(const std::string &);
void log_errno(int yoko)
{
log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
}
``
[endsect]
[section Synopsis]
Library features defined in [@boost:boost/lexical_cast.hpp boost/lexical_cast.hpp]:
``
namespace boost
{
class bad_lexical_cast;
template<typename Target, typename Source>
Target lexical_cast(const Source& arg);
}
``
[section lexical_cast]
``
template<typename Target, typename Source>
Target lexical_cast(const Source& arg);
``
Returns the result of streaming arg into a standard library string-based stream and then out as a Target object. Where Target is either `std::string` or `std::wstring`, stream extraction takes the whole content of the string, including spaces, rather than relying on the default `operator>>` behavior. If the conversion is unsuccessful, a `bad_lexical_cast` exception is thrown.
The requirements on the argument and result types are:
* Source is OutputStreamable, meaning that an `operator<<` is defined that takes a `std::ostream` or `std::wostream` object on the left hand side and an instance of the argument type on the right.
* Target is InputStreamable, meaning that an `operator>>` is defined that takes a `std::istream` or `std::wistream` object on the left hand side and an instance of the result type on the right.
* Target is CopyConstructible [20.1.3].
* Target is DefaultConstructible, meaning that it is possible to default-initialize an object of that type [8.5, 20.1.4].
The character type of the underlying stream is assumed to be `char` unless either the `Source` or the `Target` requires wide-character streaming, in which case the underlying stream uses `wchar_t`, `char16_t` or `char32_t`. Wide-character streaming is currently detected for:
* Single character: `wchar_t`, `char16_t`, `char32_t`
* Arrays of characters: `wchar_t *`, `char16_t *`, `char32_t *`, `const wchar_t *`, `const char16_t *`, `const char32_t *`
* Strings: `std::basic_string`, `boost::containers::basic_string`
* `boost::iterator_range<WideCharPtr>`, where `WideCharPtr` is a pointer to wide-character or pointer to const wide-character
[important Many compilers and runtime libraries fail to make conversions using new Unicode characters. Make shure that the following code compiles and outputs nonzero values, before using new types:
``
std::cout
<< booat::lexical_cast<std::u32string>(1.0).size()
<< " "
<< booat::lexical_cast<std::u16string>(1.0).size();
``
]
Where a higher degree of control is required over conversions, `std::stringstream` and `std::wstringstream` offer a more appropriate path. Where non-stream-based conversions are required, `lexical_cast` is the wrong tool for the job and is not special-cased for such scenarios.
[endsect]
[section bad_lexical_cast]
``
class bad_lexical_cast : public std::bad_cast
{
public:
... // same member function interface as std::exception
};
``
Exception used to indicate runtime lexical_cast failure.
[endsect]
[endsect]
[/ Commenting out bad advise (this will break the ability to get correct function pointers via &lexical_cast<Target, Source>)
[section Tuning classes for fast lexical conversions]
Because of `boost::lexical_cast` optimizations for `boost::iterator_range<character_type*>`, it is possibile to make very fast lexical conversions for non zero terminated strings, substrings and user-defined classes.
Consider the following example:
``
class example_class {
char non_zero_terminated_data[10];
std::size_t data_length;
public:
example_class();
void fill_data();
const char* data() const {
return non_zero_terminated_data;
}
std::size_t size() const {
return data_length;
}
};
inline std::ostream& operator << (std::ostream& ostr, const example_class& rhs) {
return ostr << boost::make_iterator_range(rhs.data(), rhs.data() + rhs.size());
}
``
This is a good generic solution for most use cases.
But we can make it even faster for some performance critical applications. During conversion, we loose speed at:
* `std::ostream` construction (it makes some heap allocations)
* `operator <<` (it copyies one by one all the symbols to an instance of `std::ostream`)
* `std::ostream` destruction (it makes some heap deallocations)
We can avoid all of this, by specifieng an overload for `boost::lexical_cast`:
``
namespace boost {
template <class OutT>
OutT lexical_cast(const example_class& rhs) {
return boost::lexical_cast<OutT>(
boost::make_iterator_range(rhs.data(), rhs.data() + rhs.size())
);
}
}
``
Now `boost::lexical_cast<some_type>(example_class_instance)` conversions won't copy data and construct heavy STL stream objects. See [link boost_lexical_cast.performance Performance] section for info on `boost::iterator_range` conversion performance.
[endsect]
]
[section Frequently Asked Questions]
* [*Question:] Why does `lexical_cast<int8_t>("127")` throw `bad_lexical_cast`?
* [*Answer:] The type `int8_t` is a `typedef` to `char` or `signed char`. Lexical conversion to these types is simply reading a byte from source but since the source has more than one byte, the exception is thrown.
Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also
call __numericcast__:
`numeric_cast<int8_t>(lexical_cast<int>("127"));`
[pre
]
* [*Question:] Why does `lexical_cast<unsigned char>("127")` throw `bad_lexical_cast`?
* [*Answer:] Lexical conversion to any char type is simply reading a byte from source. But since the source has more than one byte, the exception is thrown.
Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also
call __numericcast__:
`numeric_cast<unsigned char>(lexical_cast<int>("127"));`
[pre
]
* [*Question:] What does `lexical_cast<std::string>` of an `int8_t` or `uint8_t` not do what I expect?
* [*Answer:] As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid
this, cast to an integer type first: `lexical_cast<std::string>(static_cast<int>(n));`
[pre
]
* [*Question:] The implementation always resets the `ios_base::skipws` flag of an underlying stream object.
It breaks my `operator>>` that works only in presence of this flag. Can you remove code that resets the flag?
* [*Answer:] May be in a future version. There is no requirement in
__proposallong__ to reset the flag but
remember that __proposalshort__ is not yet accepted by the committee. By the way, it's a great opportunity to
make your `operator>>` conform to the standard.
Read a good C++ book, study `std::sentry` and [@boost:libs/io/doc/ios_state.html `ios_state_saver`].
[pre
]
* [*Question:] Why `std::cout << boost::lexical_cast<unsigned int>("-1");` does not throw, but outputs 4294967295?
* [*Answer:] `boost::lexical_cast` has the behavior of `std::stringstream`, which uses `num_get` functions of
`std::locale` to convert numbers. If we look at the Programming languages — C++, we'll see, that `num_get` uses
the rules of `scanf` for conversions. And in the C99 standard for unsigned input value minus sign is optional, so
if a negative number is read, no errors will arise and the result will be the two's complement.
[pre
]
* [*Question:] Why `boost::lexical_cast<int>(L'A');` outputs 65 and `boost::lexical_cast<wchar_t>(L"65");` does not throw?
* [*Answer:] If you are using an old version of Visual Studio or compile code with /Zc:wchar_t- flag,
`boost::lexical_cast` sees single `wchar_t` character as `unsigned short`. It is not a `boost::lexical_cast` mistake, but a
limitation of compiler options that you use.
[pre
]
* [*Question:] Why `boost::lexical_cast<double>("-1.#IND");` throws `boost::bad_lexical_cast`?
* [*Answer:] `"-1.#IND"` is a compiler extension, that violates standard. You shall input `"-nan"`, `"nan"`, `"inf"`
, `"-inf"` (case insensitive) strings to get NaN and Inf values. `boost::lexical_cast<string>` outputs `"-nan"`, `"nan"`,
`"inf"`, `"-inf"` strings, when has NaN or Inf input values.
* [*Question:] What is the fastest way to convert a non zero terminated string or a substring using `boost::lexical_cast`?
* [*Answer:] Use `boost::iterator_range` for conversion. For example, if you whant to convert to `int` two characters from a string `str`, you shall write `lexacal_cast<int>(make_iterator_range(str.c_str(), str.c_str() + 2));`.
[endsect]
[section Changes]
* [*boost 1.50.0 :]
* `boost::bad_lexical_cast` exception is now globaly visible and can be catched even if code is compiled with -fvisibility=hidden.
* Now it is possible to compile library with disabled exceptions.
* Better performance, less memory usage and bugfixes for `boost::iterator_range<character_type*>` conversions.
* [*boost 1.49.0 :]
* Restored work with typedefed wchar_t (compilation flag /Zc:wchar_t- for Visual Studio).
* Better performance and less memory usage for `boost::container::basic_string` conversions.
* [*boost 1.48.0 :]
* Added code to work with Inf and NaN on any platform.
* Better performance and less memory usage for conversions to float type (and to double type, if `sizeof(double) < sizeof(long double)`).
* [*boost 1.47.0 :]
* Optimizations for "C" and other locales without number grouping.
* Better performance and less memory usage for unsigned char and signed char conversions.
* Better performance and less memory usage for conversions to arithmetic types.
* Better performance and less memory usage for conversions from arithmetic type to arithmetic type.
* Directly construct Target from Source on some conversions (like conversions from string to string, from char array to string, from char to char and others).
* [*boost 1.34.0 :]
* Better performance for many combinations of Source and Target types. For more details refer to Alexander Nasonovs article [@http://accu.org/index.php/journals/1375 Fine Tuning for lexical_cast, Overload #74, August 2006] [@http://www.accu.org/var/uploads/journals/overload74.pdf (PDF)].
* [*boost 1.33.0 :]
* Call-by-const reference for the parameters. This requires partial specialization of class templates, so it doesn't work for MSVC 6, and it uses the original pass by value there.
* The MSVC 6 support is deprecated, and will be removed in a future Boost version.
* [*Earlier :]
* The previous version of lexical_cast used the default stream precision for reading and writing floating-point numbers. For numerics that have a corresponding specialization of `std::numeric_limits`, the current version now chooses a precision to match.
* The previous version of lexical_cast did not support conversion to or from any wide-character-based types. For compilers with full language and library support for wide characters, `lexical_cast` now supports conversions from `wchar_t`, `wchar_t *`, and `std::wstring` and to `wchar_t` and `std::wstring`.
* The previous version of `lexical_cast` 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 `std::string` and, where supported, `std::wstring`: `lexical_cast<std::string>("Hello, World")` succeeds instead of failing with a `bad_lexical_cast` exception.
* The previous version of `lexical_cast` allowed unsafe and meaningless conversions to pointers. The current version now throws a `bad_lexical_cast` for conversions to pointers: `lexical_cast<char *>("Goodbye, World")` now throws an exception instead of causing undefined behavior.
[endsect]
[section Performance]
In most cases `boost::lexical_cast` is faster than `scanf`, `printf`, `std::stringstream`. For more detailed info you can look at the tables below.
[section Tests description]
All the tests measure execution speed in milliseconds for 10000 iterations of the following code blocks:
[table:legend Tests source code
[[Test name] [Code]]
[[lexical_cast]
[``
_out = boost::lexical_cast<OUTTYPE>(_in);
``]
]
[[std::stringstream with construction]
[``
std::stringstream ss;
ss << _in;
if (ss.fail()) throw std::logic_error(descr);
ss >> _out;
if (ss.fail()) throw std::logic_error(descr);
``]
]
[[std::stringstream without construction]
[``
ss << _in; // ss is an instance of std::stringstream
if (ss.fail()) throw std::logic_error(descr);
ss >> _out;
if (ss.fail()) throw std::logic_error(descr);
/* reseting std::stringstream to use it again */
ss.str(std::string());
ss.clear();
``]
]
[[scanf/printf]
[``
typename OUTTYPE::value_type buffer[500];
sprintf( (char*)buffer, conv, _in);
_out = buffer;
``]
]
]
Fastest results are highlitened with "!!! *x* !!!".
Do not use this results to compare compilers, because tests were taken on different hardware.
[endsect]
[/ BEGIN of section, generated by performance measuring program ]
[section Clang version 2.9 (tags/RELEASE_29/final)]
[table:id Performance Table ( Clang version 2.9 (tags/RELEASE_29/final))
[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]]
[[ string->char ][ !!! *<1* !!! ][ 319 ][ 17 ][ 16 ]]
[[ string->signed char ][ !!! *<1* !!! ][ 192 ][ 16 ][ 9 ]]
[[ string->unsigned char ][ !!! *<1* !!! ][ 142 ][ 9 ][ 9 ]]
[[ string->int ][ !!! *7* !!! ][ 109 ][ 21 ][ 16 ]]
[[ string->short ][ !!! *6* !!! ][ 113 ][ 21 ][ 15 ]]
[[ string->long int ][ !!! *7* !!! ][ 110 ][ 22 ][ 15 ]]
[[ string->long long ][ !!! *7* !!! ][ 112 ][ 23 ][ 17 ]]
[[ string->unsigned int ][ !!! *6* !!! ][ 107 ][ 19 ][ 14 ]]
[[ string->unsigned short ][ !!! *6* !!! ][ 106 ][ 18 ][ 16 ]]
[[ string->unsigned long int ][ !!! *7* !!! ][ 108 ][ 20 ][ 15 ]]
[[ string->unsigned long long ][ !!! *7* !!! ][ 109 ][ 22 ][ 15 ]]
[[ string->float ][ !!! *14* !!! ][ 204 ][ 81 ][ 43 ]]
[[ string->double ][ !!! *24* !!! ][ 244 ][ 74 ][ 45 ]]
[[ string->long double ][ 121 ][ 170 ][ 62 ][ !!! *38* !!! ]]
[[ string->string ][ !!! *1* !!! ][ 124 ][ 25 ][ --- ]]
[[ string->container::string ][ !!! *3* !!! ][ 121 ][ 28 ][ --- ]]
[[ string->char ][ 6 ][ 115 ][ 26 ][ !!! *6* !!! ]]
[[ string->signed char ][ !!! *6* !!! ][ 115 ][ 23 ][ 21 ]]
[[ string->unsigned char ][ !!! *6* !!! ][ 113 ][ 25 ][ 22 ]]
[[ int->string ][ !!! *12* !!! ][ 128 ][ 29 ][ 19 ]]
[[ short->string ][ !!! *12* !!! ][ 128 ][ 29 ][ 21 ]]
[[ long int->string ][ !!! *12* !!! ][ 132 ][ 29 ][ 21 ]]
[[ long long->string ][ !!! *12* !!! ][ 127 ][ 29 ][ 22 ]]
[[ unsigned int->string ][ !!! *12* !!! ][ 137 ][ 33 ][ 19 ]]
[[ unsigned short->string ][ !!! *12* !!! ][ 137 ][ 31 ][ 20 ]]
[[ unsigned long int->string ][ !!! *12* !!! ][ 136 ][ 30 ][ 21 ]]
[[ unsigned long long->string ][ !!! *12* !!! ][ 128 ][ 27 ][ 23 ]]
[[ float->string ][ 51 ][ 187 ][ 82 ][ !!! *44* !!! ]]
[[ double->string ][ 56 ][ 190 ][ 83 ][ !!! *42* !!! ]]
[[ long double->string ][ 69 ][ 208 ][ 90 ][ !!! *54* !!! ]]
[[ char*->char ][ !!! *<1* !!! ][ 138 ][ 18 ][ 8 ]]
[[ char*->signed char ][ !!! *8* !!! ][ 126 ][ 10 ][ 9 ]]
[[ char*->unsigned char ][ !!! *<1* !!! ][ 98 ][ 9 ][ 9 ]]
[[ char*->int ][ !!! *8* !!! ][ 113 ][ 22 ][ 15 ]]
[[ char*->short ][ !!! *7* !!! ][ 113 ][ 22 ][ 17 ]]
[[ char*->long int ][ !!! *8* !!! ][ 111 ][ 23 ][ 15 ]]
[[ char*->long long ][ !!! *9* !!! ][ 112 ][ 24 ][ 18 ]]
[[ char*->unsigned int ][ !!! *8* !!! ][ 113 ][ 20 ][ 15 ]]
[[ char*->unsigned short ][ !!! *8* !!! ][ 113 ][ 20 ][ 15 ]]
[[ char*->unsigned long int ][ !!! *8* !!! ][ 112 ][ 21 ][ 16 ]]
[[ char*->unsigned long long ][ !!! *9* !!! ][ 110 ][ 23 ][ 14 ]]
[[ char*->float ][ !!! *14* !!! ][ 149 ][ 54 ][ 32 ]]
[[ char*->double ][ !!! *15* !!! ][ 166 ][ 59 ][ 33 ]]
[[ char*->long double ][ 122 ][ 171 ][ 63 ][ !!! *38* !!! ]]
[[ char*->string ][ !!! *7* !!! ][ 126 ][ 26 ][ --- ]]
[[ char*->container::string ][ !!! *2* !!! ][ 124 ][ 27 ][ --- ]]
[[ unsigned char*->char ][ !!! *<1* !!! ][ 99 ][ 10 ][ 8 ]]
[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 102 ][ 10 ][ 9 ]]
[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 98 ][ 10 ][ 9 ]]
[[ unsigned char*->int ][ !!! *7* !!! ][ 115 ][ 24 ][ 15 ]]
[[ unsigned char*->short ][ !!! *7* !!! ][ 115 ][ 25 ][ 17 ]]
[[ unsigned char*->long int ][ !!! *8* !!! ][ 115 ][ 22 ][ 16 ]]
[[ unsigned char*->long long ][ !!! *8* !!! ][ 116 ][ 23 ][ 16 ]]
[[ unsigned char*->unsigned int ][ !!! *8* !!! ][ 113 ][ 20 ][ 14 ]]
[[ unsigned char*->unsigned short ][ !!! *7* !!! ][ 114 ][ 21 ][ 15 ]]
[[ unsigned char*->unsigned long int ][ !!! *8* !!! ][ 114 ][ 21 ][ 14 ]]
[[ unsigned char*->unsigned long long ][ !!! *9* !!! ][ 112 ][ 23 ][ 16 ]]
[[ unsigned char*->float ][ !!! *14* !!! ][ 149 ][ 52 ][ 32 ]]
[[ unsigned char*->double ][ !!! *15* !!! ][ 165 ][ 59 ][ 33 ]]
[[ unsigned char*->long double ][ 122 ][ 172 ][ 63 ][ !!! *37* !!! ]]
[[ unsigned char*->string ][ !!! *8* !!! ][ 125 ][ 26 ][ --- ]]
[[ unsigned char*->container::string ][ !!! *4* !!! ][ 119 ][ 26 ][ --- ]]
[[ signed char*->char ][ !!! *<1* !!! ][ 98 ][ 10 ][ 8 ]]
[[ signed char*->signed char ][ !!! *<1* !!! ][ 95 ][ 10 ][ 9 ]]
[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 98 ][ 9 ][ 9 ]]
[[ signed char*->int ][ !!! *8* !!! ][ 111 ][ 21 ][ 15 ]]
[[ signed char*->short ][ !!! *7* !!! ][ 114 ][ 22 ][ 16 ]]
[[ signed char*->long int ][ !!! *8* !!! ][ 113 ][ 22 ][ 17 ]]
[[ signed char*->long long ][ !!! *8* !!! ][ 116 ][ 24 ][ 17 ]]
[[ signed char*->unsigned int ][ !!! *8* !!! ][ 109 ][ 20 ][ 15 ]]
[[ signed char*->unsigned short ][ !!! *8* !!! ][ 111 ][ 20 ][ 14 ]]
[[ signed char*->unsigned long int ][ !!! *8* !!! ][ 109 ][ 22 ][ 15 ]]
[[ signed char*->unsigned long long ][ !!! *8* !!! ][ 111 ][ 23 ][ 15 ]]
[[ signed char*->float ][ !!! *14* !!! ][ 150 ][ 53 ][ 32 ]]
[[ signed char*->double ][ !!! *15* !!! ][ 168 ][ 59 ][ 30 ]]
[[ signed char*->long double ][ 123 ][ 174 ][ 62 ][ !!! *37* !!! ]]
[[ signed char*->string ][ !!! *8* !!! ][ 127 ][ 28 ][ --- ]]
[[ signed char*->container::string ][ !!! *4* !!! ][ 124 ][ 27 ][ --- ]]
[[ iterator_range<char*>->char ][ !!! *<1* !!! ][ 103 ][ 13 ][ 8 ]]
[[ iterator_range<char*>->signed char ][ !!! *<1* !!! ][ 107 ][ 13 ][ 9 ]]
[[ iterator_range<char*>->unsigned char ][ !!! *<1* !!! ][ 121 ][ 26 ][ 13 ]]
[[ iterator_range<char*>->int ][ !!! *6* !!! ][ 165 ][ 33 ][ 23 ]]
[[ iterator_range<char*>->short ][ !!! *8* !!! ][ 175 ][ 34 ][ 29 ]]
[[ iterator_range<char*>->long int ][ !!! *14* !!! ][ 160 ][ 33 ][ 23 ]]
[[ iterator_range<char*>->long long ][ !!! *10* !!! ][ 199 ][ 35 ][ 28 ]]
[[ iterator_range<char*>->unsigned int ][ !!! *6* !!! ][ 131 ][ 24 ][ 16 ]]
[[ iterator_range<char*>->unsigned short ][ !!! *7* !!! ][ 110 ][ 22 ][ 16 ]]
[[ iterator_range<char*>->unsigned long int ][ !!! *7* !!! ][ 111 ][ 22 ][ 14 ]]
[[ iterator_range<char*>->unsigned long long ][ !!! *8* !!! ][ 115 ][ 24 ][ 15 ]]
[[ iterator_range<char*>->float ][ !!! *13* !!! ][ 134 ][ 40 ][ 33 ]]
[[ iterator_range<char*>->double ][ !!! *15* !!! ][ 140 ][ 59 ][ 41 ]]
[[ iterator_range<char*>->long double ][ 131 ][ 146 ][ 53 ][ !!! *38* !!! ]]
[[ iterator_range<char*>->string ][ !!! *9* !!! ][ 121 ][ 31 ][ --- ]]
[[ iterator_range<char*>->container::string ][ !!! *4* !!! ][ 115 ][ 25 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 113 ][ 25 ][ --- ]]
[[ float->double ][ !!! *<1* !!! ][ 234 ][ 117 ][ --- ]]
[[ char->signed char ][ !!! *<1* !!! ][ 97 ][ 9 ][ --- ]]
]
[endsect]
[section GNU C++ version 4.6.1]
[table:id Performance Table ( GNU C++ version 4.6.1)
[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]]
[[ string->char ][ !!! *<1* !!! ][ 140 ][ 17 ][ 13 ]]
[[ string->signed char ][ !!! *<1* !!! ][ 129 ][ 8 ][ 10 ]]
[[ string->unsigned char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 10 ]]
[[ string->int ][ !!! *6* !!! ][ 110 ][ 20 ][ 14 ]]
[[ string->short ][ !!! *5* !!! ][ 106 ][ 20 ][ 14 ]]
[[ string->long int ][ !!! *7* !!! ][ 107 ][ 22 ][ 14 ]]
[[ string->long long ][ !!! *7* !!! ][ 112 ][ 21 ][ 14 ]]
[[ string->unsigned int ][ !!! *6* !!! ][ 110 ][ 20 ][ 14 ]]
[[ string->unsigned short ][ !!! *5* !!! ][ 107 ][ 18 ][ 14 ]]
[[ string->unsigned long int ][ !!! *7* !!! ][ 108 ][ 23 ][ 14 ]]
[[ string->unsigned long long ][ !!! *7* !!! ][ 108 ][ 21 ][ 14 ]]
[[ string->float ][ !!! *12* !!! ][ 154 ][ 57 ][ 32 ]]
[[ string->double ][ !!! *11* !!! ][ 151 ][ 61 ][ 33 ]]
[[ string->long double ][ 109 ][ 187 ][ 79 ][ !!! *55* !!! ]]
[[ string->string ][ !!! *2* !!! ][ 122 ][ 27 ][ --- ]]
[[ string->container::string ][ !!! *3* !!! ][ 123 ][ 22 ][ --- ]]
[[ string->char ][ !!! *7* !!! ][ 109 ][ 27 ][ 17 ]]
[[ string->signed char ][ !!! *7* !!! ][ 110 ][ 25 ][ 22 ]]
[[ string->unsigned char ][ !!! *7* !!! ][ 112 ][ 27 ][ 24 ]]
[[ int->string ][ !!! *12* !!! ][ 187 ][ 48 ][ 37 ]]
[[ short->string ][ !!! *18* !!! ][ 133 ][ 33 ][ 20 ]]
[[ long int->string ][ !!! *12* !!! ][ 129 ][ 32 ][ 21 ]]
[[ long long->string ][ !!! *12* !!! ][ 127 ][ 35 ][ 23 ]]
[[ unsigned int->string ][ !!! *15* !!! ][ 133 ][ 31 ][ 21 ]]
[[ unsigned short->string ][ !!! *12* !!! ][ 133 ][ 31 ][ 21 ]]
[[ unsigned long int->string ][ !!! *12* !!! ][ 132 ][ 31 ][ 21 ]]
[[ unsigned long long->string ][ !!! *12* !!! ][ 127 ][ 29 ][ 24 ]]
[[ float->string ][ 53 ][ 215 ][ 103 ][ !!! *40* !!! ]]
[[ double->string ][ 58 ][ 215 ][ 103 ][ !!! *41* !!! ]]
[[ long double->string ][ 67 ][ 227 ][ 112 ][ !!! *45* !!! ]]
[[ char*->char ][ !!! *<1* !!! ][ 132 ][ 12 ][ 8 ]]
[[ char*->signed char ][ !!! *<1* !!! ][ 98 ][ 11 ][ 9 ]]
[[ char*->unsigned char ][ !!! *<1* !!! ][ 96 ][ 10 ][ 9 ]]
[[ char*->int ][ !!! *6* !!! ][ 109 ][ 22 ][ 14 ]]
[[ char*->short ][ !!! *5* !!! ][ 109 ][ 26 ][ 14 ]]
[[ char*->long int ][ !!! *7* !!! ][ 111 ][ 23 ][ 14 ]]
[[ char*->long long ][ !!! *8* !!! ][ 112 ][ 25 ][ 16 ]]
[[ char*->unsigned int ][ !!! *6* !!! ][ 113 ][ 19 ][ 14 ]]
[[ char*->unsigned short ][ !!! *6* !!! ][ 111 ][ 20 ][ 14 ]]
[[ char*->unsigned long int ][ !!! *7* !!! ][ 109 ][ 21 ][ 14 ]]
[[ char*->unsigned long long ][ !!! *7* !!! ][ 111 ][ 22 ][ 14 ]]
[[ char*->float ][ !!! *12* !!! ][ 156 ][ 62 ][ 32 ]]
[[ char*->double ][ !!! *13* !!! ][ 156 ][ 65 ][ 33 ]]
[[ char*->long double ][ 108 ][ 156 ][ 59 ][ !!! *36* !!! ]]
[[ char*->string ][ !!! *7* !!! ][ 123 ][ 29 ][ --- ]]
[[ char*->container::string ][ !!! *2* !!! ][ 116 ][ 24 ][ --- ]]
[[ unsigned char*->char ][ !!! *<1* !!! ][ 96 ][ 12 ][ 8 ]]
[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 97 ][ 9 ][ 9 ]]
[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 93 ][ 10 ][ 9 ]]
[[ unsigned char*->int ][ !!! *6* !!! ][ 110 ][ 22 ][ 14 ]]
[[ unsigned char*->short ][ !!! *6* !!! ][ 111 ][ 22 ][ 15 ]]
[[ unsigned char*->long int ][ !!! *8* !!! ][ 110 ][ 23 ][ 14 ]]
[[ unsigned char*->long long ][ !!! *7* !!! ][ 111 ][ 25 ][ 14 ]]
[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 111 ][ 21 ][ 16 ]]
[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 110 ][ 21 ][ 15 ]]
[[ unsigned char*->unsigned long int ][ !!! *8* !!! ][ 114 ][ 21 ][ 14 ]]
[[ unsigned char*->unsigned long long ][ !!! *8* !!! ][ 108 ][ 23 ][ 15 ]]
[[ unsigned char*->float ][ !!! *12* !!! ][ 154 ][ 62 ][ 33 ]]
[[ unsigned char*->double ][ !!! *14* !!! ][ 157 ][ 65 ][ 32 ]]
[[ unsigned char*->long double ][ 107 ][ 154 ][ 56 ][ !!! *36* !!! ]]
[[ unsigned char*->string ][ !!! *9* !!! ][ 122 ][ 28 ][ --- ]]
[[ unsigned char*->container::string ][ !!! *4* !!! ][ 118 ][ 26 ][ --- ]]
[[ signed char*->char ][ !!! *<1* !!! ][ 94 ][ 10 ][ 8 ]]
[[ signed char*->signed char ][ !!! *<1* !!! ][ 94 ][ 12 ][ 9 ]]
[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 95 ][ 12 ][ 9 ]]
[[ signed char*->int ][ !!! *7* !!! ][ 109 ][ 22 ][ 14 ]]
[[ signed char*->short ][ !!! *5* !!! ][ 108 ][ 22 ][ 14 ]]
[[ signed char*->long int ][ !!! *7* !!! ][ 110 ][ 23 ][ 14 ]]
[[ signed char*->long long ][ !!! *7* !!! ][ 110 ][ 25 ][ 15 ]]
[[ signed char*->unsigned int ][ !!! *6* !!! ][ 109 ][ 20 ][ 15 ]]
[[ signed char*->unsigned short ][ !!! *6* !!! ][ 107 ][ 21 ][ 14 ]]
[[ signed char*->unsigned long int ][ !!! *8* !!! ][ 111 ][ 21 ][ 14 ]]
[[ signed char*->unsigned long long ][ !!! *7* !!! ][ 109 ][ 23 ][ 14 ]]
[[ signed char*->float ][ !!! *12* !!! ][ 156 ][ 61 ][ 31 ]]
[[ signed char*->double ][ !!! *13* !!! ][ 156 ][ 68 ][ 33 ]]
[[ signed char*->long double ][ 109 ][ 159 ][ 56 ][ !!! *36* !!! ]]
[[ signed char*->string ][ !!! *9* !!! ][ 123 ][ 28 ][ --- ]]
[[ signed char*->container::string ][ !!! *4* !!! ][ 125 ][ 25 ][ --- ]]
[[ iterator_range<char*>->char ][ !!! *<1* !!! ][ 100 ][ 13 ][ 8 ]]
[[ iterator_range<char*>->signed char ][ !!! *<1* !!! ][ 98 ][ 14 ][ 9 ]]
[[ iterator_range<char*>->unsigned char ][ !!! *<1* !!! ][ 99 ][ 12 ][ 10 ]]
[[ iterator_range<char*>->int ][ !!! *6* !!! ][ 108 ][ 21 ][ 16 ]]
[[ iterator_range<char*>->short ][ !!! *5* !!! ][ 110 ][ 22 ][ 17 ]]
[[ iterator_range<char*>->long int ][ !!! *7* !!! ][ 107 ][ 22 ][ 15 ]]
[[ iterator_range<char*>->long long ][ !!! *7* !!! ][ 110 ][ 27 ][ 15 ]]
[[ iterator_range<char*>->unsigned int ][ !!! *6* !!! ][ 107 ][ 24 ][ 15 ]]
[[ iterator_range<char*>->unsigned short ][ !!! *5* !!! ][ 106 ][ 21 ][ 15 ]]
[[ iterator_range<char*>->unsigned long int ][ !!! *7* !!! ][ 110 ][ 21 ][ 16 ]]
[[ iterator_range<char*>->unsigned long long ][ !!! *7* !!! ][ 109 ][ 23 ][ 16 ]]
[[ iterator_range<char*>->float ][ !!! *11* !!! ][ 137 ][ 46 ][ 33 ]]
[[ iterator_range<char*>->double ][ !!! *11* !!! ][ 131 ][ 50 ][ 33 ]]
[[ iterator_range<char*>->long double ][ 107 ][ 136 ][ 44 ][ !!! *39* !!! ]]
[[ iterator_range<char*>->string ][ !!! *8* !!! ][ 117 ][ 32 ][ --- ]]
[[ iterator_range<char*>->container::string ][ !!! *3* !!! ][ 111 ][ 23 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 110 ][ 33 ][ --- ]]
[[ float->double ][ !!! *<1* !!! ][ 241 ][ 152 ][ --- ]]
[[ char->signed char ][ !!! *<1* !!! ][ 90 ][ 8 ][ --- ]]
]
[endsect]
[section GNU C++ version 4.5.4]
[table:id Performance Table ( GNU C++ version 4.5.4)
[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]]
[[ string->char ][ !!! *<1* !!! ][ 147 ][ 12 ][ 8 ]]
[[ string->signed char ][ !!! *<1* !!! ][ 138 ][ 13 ][ 10 ]]
[[ string->unsigned char ][ !!! *<1* !!! ][ 86 ][ 12 ][ 9 ]]
[[ string->int ][ !!! *7* !!! ][ 103 ][ 20 ][ 15 ]]
[[ string->short ][ !!! *5* !!! ][ 103 ][ 20 ][ 15 ]]
[[ string->long int ][ !!! *7* !!! ][ 103 ][ 22 ][ 15 ]]
[[ string->long long ][ !!! *7* !!! ][ 104 ][ 22 ][ 16 ]]
[[ string->unsigned int ][ !!! *6* !!! ][ 108 ][ 19 ][ 15 ]]
[[ string->unsigned short ][ !!! *5* !!! ][ 104 ][ 19 ][ 15 ]]
[[ string->unsigned long int ][ !!! *7* !!! ][ 103 ][ 20 ][ 16 ]]
[[ string->unsigned long long ][ !!! *7* !!! ][ 101 ][ 22 ][ 14 ]]
[[ string->float ][ !!! *13* !!! ][ 148 ][ 58 ][ 35 ]]
[[ string->double ][ !!! *13* !!! ][ 147 ][ 60 ][ 34 ]]
[[ string->long double ][ 103 ][ 149 ][ 56 ][ !!! *38* !!! ]]
[[ string->string ][ !!! *2* !!! ][ 127 ][ 27 ][ --- ]]
[[ string->container::string ][ !!! *3* !!! ][ 101 ][ 24 ][ --- ]]
[[ string->char ][ !!! *7* !!! ][ 108 ][ 35 ][ 17 ]]
[[ string->signed char ][ !!! *7* !!! ][ 112 ][ 26 ][ 23 ]]
[[ string->unsigned char ][ !!! *7* !!! ][ 113 ][ 25 ][ 25 ]]
[[ int->string ][ !!! *11* !!! ][ 183 ][ 47 ][ 40 ]]
[[ short->string ][ !!! *14* !!! ][ 153 ][ 35 ][ 23 ]]
[[ long int->string ][ !!! *12* !!! ][ 135 ][ 32 ][ 22 ]]
[[ long long->string ][ !!! *11* !!! ][ 131 ][ 30 ][ 24 ]]
[[ unsigned int->string ][ !!! *12* !!! ][ 137 ][ 31 ][ 22 ]]
[[ unsigned short->string ][ !!! *11* !!! ][ 137 ][ 33 ][ 22 ]]
[[ unsigned long int->string ][ !!! *11* !!! ][ 136 ][ 36 ][ 23 ]]
[[ unsigned long long->string ][ !!! *11* !!! ][ 127 ][ 29 ][ 23 ]]
[[ float->string ][ 56 ][ 218 ][ 107 ][ !!! *44* !!! ]]
[[ double->string ][ 63 ][ 223 ][ 106 ][ !!! *44* !!! ]]
[[ long double->string ][ 69 ][ 229 ][ 118 ][ !!! *49* !!! ]]
[[ char*->char ][ !!! *<1* !!! ][ 91 ][ 12 ][ 9 ]]
[[ char*->signed char ][ !!! *<1* !!! ][ 100 ][ 11 ][ 11 ]]
[[ char*->unsigned char ][ !!! *<1* !!! ][ 97 ][ 12 ][ 10 ]]
[[ char*->int ][ !!! *7* !!! ][ 112 ][ 23 ][ 16 ]]
[[ char*->short ][ !!! *6* !!! ][ 116 ][ 23 ][ 16 ]]
[[ char*->long int ][ !!! *8* !!! ][ 113 ][ 23 ][ 16 ]]
[[ char*->long long ][ !!! *8* !!! ][ 122 ][ 28 ][ 16 ]]
[[ char*->unsigned int ][ !!! *6* !!! ][ 117 ][ 21 ][ 15 ]]
[[ char*->unsigned short ][ !!! *6* !!! ][ 113 ][ 21 ][ 16 ]]
[[ char*->unsigned long int ][ !!! *7* !!! ][ 118 ][ 22 ][ 16 ]]
[[ char*->unsigned long long ][ !!! *8* !!! ][ 113 ][ 22 ][ 17 ]]
[[ char*->float ][ !!! *11* !!! ][ 164 ][ 67 ][ 34 ]]
[[ char*->double ][ !!! *13* !!! ][ 163 ][ 66 ][ 35 ]]
[[ char*->long double ][ 110 ][ 164 ][ 63 ][ !!! *39* !!! ]]
[[ char*->string ][ !!! *8* !!! ][ 130 ][ 30 ][ --- ]]
[[ char*->container::string ][ !!! *2* !!! ][ 113 ][ 24 ][ --- ]]
[[ unsigned char*->char ][ !!! *<1* !!! ][ 98 ][ 11 ][ 10 ]]
[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 97 ][ 12 ][ 10 ]]
[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 97 ][ 11 ][ 10 ]]
[[ unsigned char*->int ][ !!! *7* !!! ][ 112 ][ 23 ][ 16 ]]
[[ unsigned char*->short ][ !!! *6* !!! ][ 115 ][ 22 ][ 20 ]]
[[ unsigned char*->long int ][ !!! *8* !!! ][ 112 ][ 23 ][ 15 ]]
[[ unsigned char*->long long ][ !!! *8* !!! ][ 115 ][ 29 ][ 17 ]]
[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 114 ][ 21 ][ 14 ]]
[[ unsigned char*->unsigned short ][ !!! *7* !!! ][ 112 ][ 22 ][ 15 ]]
[[ unsigned char*->unsigned long int ][ !!! *7* !!! ][ 115 ][ 23 ][ 14 ]]
[[ unsigned char*->unsigned long long ][ !!! *8* !!! ][ 112 ][ 24 ][ 15 ]]
[[ unsigned char*->float ][ !!! *12* !!! ][ 161 ][ 66 ][ 34 ]]
[[ unsigned char*->double ][ !!! *13* !!! ][ 162 ][ 66 ][ 36 ]]
[[ unsigned char*->long double ][ 112 ][ 161 ][ 63 ][ !!! *39* !!! ]]
[[ unsigned char*->string ][ !!! *9* !!! ][ 127 ][ 29 ][ --- ]]
[[ unsigned char*->container::string ][ !!! *4* !!! ][ 111 ][ 25 ][ --- ]]
[[ signed char*->char ][ !!! *<1* !!! ][ 104 ][ 11 ][ 8 ]]
[[ signed char*->signed char ][ !!! *<1* !!! ][ 98 ][ 11 ][ 11 ]]
[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 98 ][ 11 ][ 11 ]]
[[ signed char*->int ][ !!! *7* !!! ][ 112 ][ 23 ][ 16 ]]
[[ signed char*->short ][ !!! *7* !!! ][ 113 ][ 23 ][ 15 ]]
[[ signed char*->long int ][ !!! *8* !!! ][ 112 ][ 22 ][ 14 ]]
[[ signed char*->long long ][ !!! *8* !!! ][ 115 ][ 25 ][ 16 ]]
[[ signed char*->unsigned int ][ !!! *8* !!! ][ 114 ][ 21 ][ 18 ]]
[[ signed char*->unsigned short ][ !!! *6* !!! ][ 112 ][ 22 ][ 15 ]]
[[ signed char*->unsigned long int ][ !!! *8* !!! ][ 116 ][ 22 ][ 15 ]]
[[ signed char*->unsigned long long ][ !!! *8* !!! ][ 113 ][ 23 ][ 16 ]]
[[ signed char*->float ][ !!! *13* !!! ][ 161 ][ 65 ][ 34 ]]
[[ signed char*->double ][ !!! *12* !!! ][ 172 ][ 67 ][ 34 ]]
[[ signed char*->long double ][ 110 ][ 164 ][ 63 ][ !!! *38* !!! ]]
[[ signed char*->string ][ !!! *9* !!! ][ 131 ][ 30 ][ --- ]]
[[ signed char*->container::string ][ !!! *4* !!! ][ 112 ][ 24 ][ --- ]]
[[ iterator_range<char*>->char ][ !!! *<1* !!! ][ 103 ][ 12 ][ 8 ]]
[[ iterator_range<char*>->signed char ][ !!! *<1* !!! ][ 101 ][ 13 ][ 9 ]]
[[ iterator_range<char*>->unsigned char ][ !!! *<1* !!! ][ 103 ][ 13 ][ 10 ]]
[[ iterator_range<char*>->int ][ !!! *7* !!! ][ 113 ][ 26 ][ 14 ]]
[[ iterator_range<char*>->short ][ !!! *5* !!! ][ 115 ][ 21 ][ 16 ]]
[[ iterator_range<char*>->long int ][ !!! *7* !!! ][ 115 ][ 22 ][ 15 ]]
[[ iterator_range<char*>->long long ][ !!! *7* !!! ][ 116 ][ 25 ][ 16 ]]
[[ iterator_range<char*>->unsigned int ][ !!! *6* !!! ][ 115 ][ 24 ][ 23 ]]
[[ iterator_range<char*>->unsigned short ][ !!! *5* !!! ][ 113 ][ 22 ][ 16 ]]
[[ iterator_range<char*>->unsigned long int ][ !!! *7* !!! ][ 117 ][ 20 ][ 16 ]]
[[ iterator_range<char*>->unsigned long long ][ !!! *7* !!! ][ 114 ][ 21 ][ 16 ]]
[[ iterator_range<char*>->float ][ !!! *11* !!! ][ 145 ][ 51 ][ 34 ]]
[[ iterator_range<char*>->double ][ !!! *11* !!! ][ 139 ][ 53 ][ 35 ]]
[[ iterator_range<char*>->long double ][ 109 ][ 147 ][ 44 ][ !!! *38* !!! ]]
[[ iterator_range<char*>->string ][ !!! *9* !!! ][ 123 ][ 36 ][ --- ]]
[[ iterator_range<char*>->container::string ][ !!! *3* !!! ][ 113 ][ 20 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 117 ][ 23 ][ --- ]]
[[ float->double ][ !!! *<1* !!! ][ 262 ][ 150 ][ --- ]]
[[ char->signed char ][ !!! *<1* !!! ][ 97 ][ 9 ][ --- ]]
]
[endsect]
[section GNU C++ version 4.4.6]
[table:id Performance Table ( GNU C++ version 4.4.6)
[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]]
[[ string->char ][ !!! *<1* !!! ][ 162 ][ 17 ][ 8 ]]
[[ string->signed char ][ !!! *<1* !!! ][ 103 ][ 9 ][ 9 ]]
[[ string->unsigned char ][ !!! *<1* !!! ][ 91 ][ 9 ][ 9 ]]
[[ string->int ][ !!! *6* !!! ][ 104 ][ 21 ][ 14 ]]
[[ string->short ][ !!! *5* !!! ][ 107 ][ 22 ][ 14 ]]
[[ string->long int ][ !!! *7* !!! ][ 106 ][ 23 ][ 15 ]]
[[ string->long long ][ !!! *7* !!! ][ 104 ][ 21 ][ 16 ]]
[[ string->unsigned int ][ !!! *6* !!! ][ 100 ][ 20 ][ 16 ]]
[[ string->unsigned short ][ !!! *5* !!! ][ 102 ][ 20 ][ 16 ]]
[[ string->unsigned long int ][ !!! *7* !!! ][ 106 ][ 25 ][ 16 ]]
[[ string->unsigned long long ][ !!! *7* !!! ][ 109 ][ 25 ][ 14 ]]
[[ string->float ][ !!! *13* !!! ][ 142 ][ 48 ][ 32 ]]
[[ string->double ][ !!! *13* !!! ][ 162 ][ 62 ][ 33 ]]
[[ string->long double ][ 119 ][ 164 ][ 62 ][ !!! *37* !!! ]]
[[ string->string ][ !!! *2* !!! ][ 122 ][ 27 ][ --- ]]
[[ string->container::string ][ !!! *2* !!! ][ 107 ][ 23 ][ --- ]]
[[ string->char ][ !!! *6* !!! ][ 110 ][ 24 ][ 15 ]]
[[ string->signed char ][ !!! *6* !!! ][ 107 ][ 24 ][ 21 ]]
[[ string->unsigned char ][ !!! *6* !!! ][ 106 ][ 27 ][ 21 ]]
[[ int->string ][ !!! *12* !!! ][ 122 ][ 31 ][ 21 ]]
[[ short->string ][ !!! *12* !!! ][ 136 ][ 29 ][ 20 ]]
[[ long int->string ][ !!! *12* !!! ][ 127 ][ 32 ][ 19 ]]
[[ long long->string ][ !!! *12* !!! ][ 121 ][ 32 ][ 21 ]]
[[ unsigned int->string ][ !!! *12* !!! ][ 133 ][ 32 ][ 19 ]]
[[ unsigned short->string ][ !!! *12* !!! ][ 126 ][ 33 ][ 20 ]]
[[ unsigned long int->string ][ !!! *11* !!! ][ 126 ][ 34 ][ 19 ]]
[[ unsigned long long->string ][ !!! *12* !!! ][ 125 ][ 28 ][ 21 ]]
[[ float->string ][ 47 ][ 183 ][ 86 ][ !!! *43* !!! ]]
[[ double->string ][ 57 ][ 184 ][ 90 ][ !!! *42* !!! ]]
[[ long double->string ][ 64 ][ 199 ][ 87 ][ !!! *46* !!! ]]
[[ char*->char ][ !!! *<1* !!! ][ 95 ][ 10 ][ 8 ]]
[[ char*->signed char ][ !!! *<1* !!! ][ 90 ][ 12 ][ 9 ]]
[[ char*->unsigned char ][ !!! *<1* !!! ][ 93 ][ 12 ][ 9 ]]
[[ char*->int ][ !!! *6* !!! ][ 108 ][ 24 ][ 14 ]]
[[ char*->short ][ !!! *6* !!! ][ 106 ][ 23 ][ 14 ]]
[[ char*->long int ][ !!! *7* !!! ][ 107 ][ 24 ][ 17 ]]
[[ char*->long long ][ !!! *7* !!! ][ 109 ][ 25 ][ 17 ]]
[[ char*->unsigned int ][ !!! *6* !!! ][ 104 ][ 23 ][ 17 ]]
[[ char*->unsigned short ][ !!! *6* !!! ][ 102 ][ 22 ][ 17 ]]
[[ char*->unsigned long int ][ !!! *7* !!! ][ 107 ][ 23 ][ 17 ]]
[[ char*->unsigned long long ][ !!! *7* !!! ][ 115 ][ 26 ][ 14 ]]
[[ char*->float ][ !!! *12* !!! ][ 150 ][ 56 ][ 30 ]]
[[ char*->double ][ !!! *12* !!! ][ 165 ][ 66 ][ 32 ]]
[[ char*->long double ][ 116 ][ 173 ][ 66 ][ !!! *37* !!! ]]
[[ char*->string ][ !!! *7* !!! ][ 120 ][ 28 ][ --- ]]
[[ char*->container::string ][ !!! *2* !!! ][ 108 ][ 26 ][ --- ]]
[[ unsigned char*->char ][ !!! *<1* !!! ][ 90 ][ 12 ][ 8 ]]
[[ unsigned char*->signed char ][ !!! *<1* !!! ][ 91 ][ 11 ][ 9 ]]
[[ unsigned char*->unsigned char ][ !!! *<1* !!! ][ 91 ][ 12 ][ 9 ]]
[[ unsigned char*->int ][ !!! *6* !!! ][ 106 ][ 24 ][ 14 ]]
[[ unsigned char*->short ][ !!! *6* !!! ][ 108 ][ 24 ][ 14 ]]
[[ unsigned char*->long int ][ !!! *7* !!! ][ 116 ][ 23 ][ 14 ]]
[[ unsigned char*->long long ][ !!! *7* !!! ][ 108 ][ 28 ][ 14 ]]
[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 107 ][ 22 ][ 14 ]]
[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 105 ][ 21 ][ 16 ]]
[[ unsigned char*->unsigned long int ][ !!! *7* !!! ][ 106 ][ 25 ][ 16 ]]
[[ unsigned char*->unsigned long long ][ !!! *7* !!! ][ 105 ][ 24 ][ 17 ]]
[[ unsigned char*->float ][ !!! *14* !!! ][ 150 ][ 57 ][ 33 ]]
[[ unsigned char*->double ][ !!! *14* !!! ][ 171 ][ 72 ][ 34 ]]
[[ unsigned char*->long double ][ 118 ][ 171 ][ 73 ][ !!! *38* !!! ]]
[[ unsigned char*->string ][ !!! *8* !!! ][ 120 ][ 29 ][ --- ]]
[[ unsigned char*->container::string ][ !!! *3* !!! ][ 114 ][ 26 ][ --- ]]
[[ signed char*->char ][ !!! *<1* !!! ][ 92 ][ 12 ][ 8 ]]
[[ signed char*->signed char ][ !!! *<1* !!! ][ 92 ][ 12 ][ 9 ]]
[[ signed char*->unsigned char ][ !!! *<1* !!! ][ 91 ][ 14 ][ 9 ]]
[[ signed char*->int ][ !!! *6* !!! ][ 109 ][ 22 ][ 15 ]]
[[ signed char*->short ][ !!! *6* !!! ][ 106 ][ 24 ][ 17 ]]
[[ signed char*->long int ][ !!! *7* !!! ][ 107 ][ 24 ][ 16 ]]
[[ signed char*->long long ][ !!! *7* !!! ][ 106 ][ 24 ][ 14 ]]
[[ signed char*->unsigned int ][ !!! *6* !!! ][ 106 ][ 22 ][ 14 ]]
[[ signed char*->unsigned short ][ !!! *6* !!! ][ 104 ][ 20 ][ 14 ]]
[[ signed char*->unsigned long int ][ !!! *7* !!! ][ 105 ][ 22 ][ 16 ]]
[[ signed char*->unsigned long long ][ !!! *7* !!! ][ 108 ][ 24 ][ 15 ]]
[[ signed char*->float ][ !!! *14* !!! ][ 147 ][ 54 ][ 32 ]]
[[ signed char*->double ][ !!! *14* !!! ][ 170 ][ 68 ][ 37 ]]
[[ signed char*->long double ][ 133 ][ 167 ][ 66 ][ !!! *37* !!! ]]
[[ signed char*->string ][ !!! *8* !!! ][ 119 ][ 30 ][ --- ]]
[[ signed char*->container::string ][ !!! *3* !!! ][ 108 ][ 24 ][ --- ]]
[[ iterator_range<char*>->char ][ !!! *<1* !!! ][ 98 ][ 13 ][ 8 ]]
[[ iterator_range<char*>->signed char ][ !!! *<1* !!! ][ 98 ][ 15 ][ 9 ]]
[[ iterator_range<char*>->unsigned char ][ !!! *<1* !!! ][ 97 ][ 15 ][ 9 ]]
[[ iterator_range<char*>->int ][ !!! *6* !!! ][ 107 ][ 27 ][ 14 ]]
[[ iterator_range<char*>->short ][ !!! *5* !!! ][ 109 ][ 23 ][ 14 ]]
[[ iterator_range<char*>->long int ][ !!! *7* !!! ][ 109 ][ 22 ][ 14 ]]
[[ iterator_range<char*>->long long ][ !!! *7* !!! ][ 107 ][ 24 ][ 14 ]]
[[ iterator_range<char*>->unsigned int ][ !!! *6* !!! ][ 120 ][ 23 ][ 14 ]]
[[ iterator_range<char*>->unsigned short ][ !!! *5* !!! ][ 104 ][ 21 ][ 17 ]]
[[ iterator_range<char*>->unsigned long int ][ !!! *8* !!! ][ 108 ][ 25 ][ 16 ]]
[[ iterator_range<char*>->unsigned long long ][ !!! *7* !!! ][ 106 ][ 25 ][ 15 ]]
[[ iterator_range<char*>->float ][ !!! *13* !!! ][ 132 ][ 41 ][ 32 ]]
[[ iterator_range<char*>->double ][ !!! *12* !!! ][ 136 ][ 45 ][ 32 ]]
[[ iterator_range<char*>->long double ][ 113 ][ 138 ][ 50 ][ !!! *36* !!! ]]
[[ iterator_range<char*>->string ][ !!! *7* !!! ][ 114 ][ 33 ][ --- ]]
[[ iterator_range<char*>->container::string ][ !!! *2* !!! ][ 105 ][ 24 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 112 ][ 31 ][ --- ]]
[[ float->double ][ !!! *<1* !!! ][ 233 ][ 199 ][ --- ]]
[[ char->signed char ][ !!! *<1* !!! ][ 129 ][ 10 ][ --- ]]
]
[endsect]
[/ END of section, generated by performance measuring program ]
[endsect]
+295 -18
View File
@@ -1,6 +1,6 @@
// boost cast.hpp header file ----------------------------------------------//
// (C) Copyright Kevlin Henney and Dave Abrahams 1999.
// (C) Copyright Kevlin Henney and Dave Abrahams 1999.
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -8,10 +8,9 @@
// See http://www.boost.org/libs/conversion for Documentation.
// Revision History
// 23 JUn 05 numeric_cast removed and redirected to the new verion (Fernando Cacciola)
// 02 Apr 01 Removed BOOST_NO_LIMITS workarounds and included
// <boost/limits.hpp> instead (the workaround did not
// actually compile when BOOST_NO_LIMITS was defined in
// 02 Apr 01 Removed BOOST_NO_LIMITS workarounds and included
// <boost/limits.hpp> instead (the workaround did not
// actually compile when BOOST_NO_LIMITS was defined in
// any case, so we loose nothing). (John Maddock)
// 21 Jan 01 Undid a bug I introduced yesterday. numeric_cast<> never
// worked with stock GCC; trying to get it to do that broke
@@ -27,14 +26,14 @@
// (Dave Abrahams)
// 30 Jun 00 More MSVC6 wordarounds. See comments below. (Dave Abrahams)
// 28 Jun 00 Removed implicit_cast<>. See comment below. (Beman Dawes)
// 27 Jun 00 More MSVC6 workarounds
// 27 Jun 00 More MSVC6 workarounds
// 15 Jun 00 Add workarounds for MSVC6
// 2 Feb 00 Remove bad_numeric_cast ";" syntax error (Doncho Angelov)
// 26 Jan 00 Add missing throw() to bad_numeric_cast::what(0 (Adam Levar)
// 29 Dec 99 Change using declarations so usages in other namespaces work
// correctly (Dave Abrahams)
// 23 Sep 99 Change polymorphic_downcast assert to also detect M.I. errors
// as suggested Darin Adler and improved by Valentin Bonnard.
// as suggested Darin Adler and improved by Valentin Bonnard.
// 2 Sep 99 Remove controversial asserts, simplify, rename.
// 30 Aug 99 Move to cast.hpp, replace value_cast with numeric_cast,
// place in nested namespace.
@@ -44,7 +43,7 @@
#define BOOST_CAST_HPP
# include <boost/config.hpp>
# include <boost/assert.hpp>
# include <cassert>
# include <typeinfo>
# include <boost/type.hpp>
# include <boost/limits.hpp>
@@ -55,7 +54,7 @@
// appear in the function's argument list.
//
// TODO: Add this to config.hpp?
# if defined(BOOST_MSVC) && BOOST_MSVC < 1300
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200 // 1200 = VC6
# define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::type<Target>* = 0
# else
# define BOOST_EXPLICIT_DEFAULT_TARGET
@@ -69,7 +68,7 @@ namespace boost
// polymorphic_cast --------------------------------------------------------//
// Runtime checked polymorphic downcasts and crosscasts.
// Suggested in The C++ Programming Language, 3rd Ed, Bjarne Stroustrup,
// Suggested in The C++ Programming Language, 3rd Ed, Bjarne Stroustrup,
// section 15.8 exercise 1, page 425.
template <class Target, class Source>
@@ -82,26 +81,304 @@ namespace boost
// polymorphic_downcast ----------------------------------------------------//
// BOOST_ASSERT() checked polymorphic downcast. Crosscasts prohibited.
// assert() checked polymorphic downcast. Crosscasts prohibited.
// WARNING: Because this cast uses BOOST_ASSERT(), it violates
// the One Definition Rule if used in multiple translation units
// where BOOST_DISABLE_ASSERTS, BOOST_ENABLE_ASSERT_HANDLER
// NDEBUG are defined inconsistently.
// WARNING: Because this cast uses assert(), it violates the One Definition
// Rule if NDEBUG is inconsistently defined across translation units.
// Contributed by Dave Abrahams
template <class Target, class Source>
inline Target polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
{
BOOST_ASSERT( dynamic_cast<Target>(x) == x ); // detect logic error
assert( dynamic_cast<Target>(x) == x ); // detect logic error
return static_cast<Target>(x);
}
// implicit_cast -----------------------------------------------------------//
//
// Removed due to uncertain purpose. Use either numeric_cast (see below)
// or static_cast according to the need.
// numeric_cast and related exception --------------------------------------//
// Contributed by Kevlin Henney
// bad_numeric_cast --------------------------------------------------------//
// exception used to indicate runtime numeric_cast failure
class bad_numeric_cast : public std::bad_cast
{
public:
// constructors, destructors and assignment operator defaulted
// function inlined for brevity and consistency with rest of library
virtual const char *what() const throw()
{
return "bad numeric cast: loss of range in numeric_cast";
}
};
// numeric_cast ------------------------------------------------------------//
#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_SGI_CPP_LIMITS)
namespace detail
{
template <class T>
struct signed_numeric_limits : std::numeric_limits<T>
{
static inline T min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{
return (std::numeric_limits<T>::min)() >= 0
// unary minus causes integral promotion, thus the static_cast<>
? static_cast<T>(-(std::numeric_limits<T>::max)())
: (std::numeric_limits<T>::min)();
};
};
// Move to namespace boost in utility.hpp?
template <class T, bool specialized>
struct fixed_numeric_limits_base
: public if_true< std::numeric_limits<T>::is_signed >
::BOOST_NESTED_TEMPLATE then< signed_numeric_limits<T>,
std::numeric_limits<T>
>::type
{};
template <class T>
struct fixed_numeric_limits
: fixed_numeric_limits_base<T,(std::numeric_limits<T>::is_specialized)>
{};
# ifdef BOOST_HAS_LONG_LONG
// cover implementations which supply no specialization for long
// long / unsigned long long. Not intended to be full
// numeric_limits replacements, but good enough for numeric_cast<>
template <>
struct fixed_numeric_limits_base< ::boost::long_long_type, false>
{
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
BOOST_STATIC_CONSTANT(bool, is_signed = true);
static ::boost::long_long_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{
# ifdef LONGLONG_MAX
return LONGLONG_MAX;
# else
return 9223372036854775807LL; // hope this is portable
# endif
}
static ::boost::long_long_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{
# ifdef LONGLONG_MIN
return LONGLONG_MIN;
# else
return -( 9223372036854775807LL )-1; // hope this is portable
# endif
}
};
template <>
struct fixed_numeric_limits_base< ::boost::ulong_long_type, false>
{
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
BOOST_STATIC_CONSTANT(bool, is_signed = false);
static ::boost::ulong_long_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{
# ifdef ULONGLONG_MAX
return ULONGLONG_MAX;
# else
return 0xffffffffffffffffULL; // hope this is portable
# endif
}
static ::boost::ulong_long_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; }
};
# endif
} // namespace detail
// less_than_type_min -
// x_is_signed should be numeric_limits<X>::is_signed
// y_is_signed should be numeric_limits<Y>::is_signed
// y_min should be numeric_limits<Y>::min()
//
// check(x, y_min) returns true iff x < y_min without invoking comparisons
// between signed and unsigned values.
//
// "poor man's partial specialization" is in use here.
template <bool x_is_signed, bool y_is_signed>
struct less_than_type_min
{
template <class X, class Y>
static bool check(X x, Y y_min)
{ return x < y_min; }
};
template <>
struct less_than_type_min<false, true>
{
template <class X, class Y>
static bool check(X, Y)
{ return false; }
};
template <>
struct less_than_type_min<true, false>
{
template <class X, class Y>
static bool check(X x, Y)
{ return x < 0; }
};
// greater_than_type_max -
// same_sign should be:
// numeric_limits<X>::is_signed == numeric_limits<Y>::is_signed
// y_max should be numeric_limits<Y>::max()
//
// check(x, y_max) returns true iff x > y_max without invoking comparisons
// between signed and unsigned values.
//
// "poor man's partial specialization" is in use here.
template <bool same_sign, bool x_is_signed>
struct greater_than_type_max;
template<>
struct greater_than_type_max<true, true>
{
template <class X, class Y>
static inline bool check(X x, Y y_max)
{ return x > y_max; }
};
template <>
struct greater_than_type_max<false, true>
{
// What does the standard say about this? I think it's right, and it
// will work with every compiler I know of.
template <class X, class Y>
static inline bool check(X x, Y)
{ return x >= 0 && static_cast<X>(static_cast<Y>(x)) != x; }
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1200
// MSVC6 can't static_cast unsigned __int64 -> floating types
# define BOOST_UINT64_CAST(src_type) \
static inline bool check(src_type x, unsigned __int64) \
{ \
if (x < 0) return false; \
unsigned __int64 y = static_cast<unsigned __int64>(x); \
bool odd = y & 0x1; \
__int64 div2 = static_cast<__int64>(y >> 1); \
return ((static_cast<src_type>(div2) * 2.0) + odd) != x; \
}
BOOST_UINT64_CAST(long double);
BOOST_UINT64_CAST(double);
BOOST_UINT64_CAST(float);
# undef BOOST_UINT64_CAST
# endif
};
template<>
struct greater_than_type_max<true, false>
{
template <class X, class Y>
static inline bool check(X x, Y y_max)
{ return x > y_max; }
};
template <>
struct greater_than_type_max<false, false>
{
// What does the standard say about this? I think it's right, and it
// will work with every compiler I know of.
template <class X, class Y>
static inline bool check(X x, Y)
{ return static_cast<X>(static_cast<Y>(x)) != x; }
};
#else // use #pragma hacks if available
namespace detail
{
# if BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4018)
# pragma warning(disable : 4146)
#elif defined(__BORLANDC__)
# pragma option push -w-8041
# endif
// Move to namespace boost in utility.hpp?
template <class T>
struct fixed_numeric_limits : public std::numeric_limits<T>
{
static inline T min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{
return std::numeric_limits<T>::is_signed && (std::numeric_limits<T>::min)() >= 0
? T(-(std::numeric_limits<T>::max)()) : (std::numeric_limits<T>::min)();
}
};
# if BOOST_MSVC
# pragma warning(pop)
#elif defined(__BORLANDC__)
# pragma option pop
# endif
} // namespace detail
#endif
template<typename Target, typename Source>
inline Target numeric_cast(Source arg BOOST_EXPLICIT_DEFAULT_TARGET)
{
// typedefs abbreviating respective trait classes
typedef detail::fixed_numeric_limits<Source> arg_traits;
typedef detail::fixed_numeric_limits<Target> result_traits;
#if defined(BOOST_STRICT_CONFIG) \
|| (!defined(__HP_aCC) || __HP_aCC > 33900) \
&& (!defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) \
|| defined(BOOST_SGI_CPP_LIMITS))
// typedefs that act as compile time assertions
// (to be replaced by boost compile time assertions
// as and when they become available and are stable)
typedef bool argument_must_be_numeric[arg_traits::is_specialized];
typedef bool result_must_be_numeric[result_traits::is_specialized];
const bool arg_is_signed = arg_traits::is_signed;
const bool result_is_signed = result_traits::is_signed;
const bool same_sign = arg_is_signed == result_is_signed;
if (less_than_type_min<arg_is_signed, result_is_signed>::check(arg, (result_traits::min)())
|| greater_than_type_max<same_sign, arg_is_signed>::check(arg, (result_traits::max)())
)
#else // We need to use #pragma hacks if available
# if BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4018)
#elif defined(__BORLANDC__)
#pragma option push -w-8012
# endif
if ((arg < 0 && !result_traits::is_signed) // loss of negative range
|| (arg_traits::is_signed && arg < (result_traits::min)()) // underflow
|| arg > (result_traits::max)()) // overflow
# if BOOST_MSVC
# pragma warning(pop)
#elif defined(__BORLANDC__)
#pragma option pop
# endif
#endif
{
throw bad_numeric_cast();
}
return static_cast<Target>(arg);
} // numeric_cast
# undef BOOST_EXPLICIT_DEFAULT_TARGET
} // namespace boost
# include <boost/numeric/conversion/cast.hpp>
#endif // BOOST_CAST_HPP
-184
View File
@@ -1,184 +0,0 @@
// Copyright Alexander Nasonov & Paul A. Bristow 2006.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
#define BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
#include <climits>
#include <ios>
#include <limits>
#include <boost/config.hpp>
#include <boost/integer_traits.hpp>
#ifndef BOOST_NO_IS_ABSTRACT
// Fix for SF:1358600 - lexical_cast & pure virtual functions & VC 8 STL
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_abstract.hpp>
#endif
#if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || \
(defined(BOOST_MSVC) && (BOOST_MSVC<1310))
#define BOOST_LCAST_NO_COMPILE_TIME_PRECISION
#endif
#ifdef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
#include <boost/assert.hpp>
#else
#include <boost/static_assert.hpp>
#endif
namespace boost { namespace detail {
class lcast_abstract_stub {};
#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
// Calculate an argument to pass to std::ios_base::precision from
// lexical_cast. See alternative implementation for broken standard
// libraries in lcast_get_precision below. Keep them in sync, please.
template<class T>
struct lcast_precision
{
#ifdef BOOST_NO_IS_ABSTRACT
typedef std::numeric_limits<T> limits; // No fix for SF:1358600.
#else
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
boost::is_abstract<T>
, std::numeric_limits<lcast_abstract_stub>
, std::numeric_limits<T>
>::type limits;
#endif
BOOST_STATIC_CONSTANT(bool, use_default_precision =
!limits::is_specialized || limits::is_exact
);
BOOST_STATIC_CONSTANT(bool, is_specialized_bin =
!use_default_precision &&
limits::radix == 2 && limits::digits > 0
);
BOOST_STATIC_CONSTANT(bool, is_specialized_dec =
!use_default_precision &&
limits::radix == 10 && limits::digits10 > 0
);
BOOST_STATIC_CONSTANT(std::streamsize, streamsize_max =
boost::integer_traits<std::streamsize>::const_max
);
BOOST_STATIC_CONSTANT(unsigned int, precision_dec = limits::digits10 + 1U);
BOOST_STATIC_ASSERT(!is_specialized_dec ||
precision_dec <= streamsize_max + 0UL
);
BOOST_STATIC_CONSTANT(unsigned long, precision_bin =
2UL + limits::digits * 30103UL / 100000UL
);
BOOST_STATIC_ASSERT(!is_specialized_bin ||
(limits::digits + 0UL < ULONG_MAX / 30103UL &&
precision_bin > limits::digits10 + 0UL &&
precision_bin <= streamsize_max + 0UL)
);
BOOST_STATIC_CONSTANT(std::streamsize, value =
is_specialized_bin ? precision_bin
: is_specialized_dec ? precision_dec : 6
);
};
#endif
template<class T>
inline std::streamsize lcast_get_precision(T* = 0)
{
#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
return lcast_precision<T>::value;
#else // Follow lcast_precision algorithm at run-time:
#ifdef BOOST_NO_IS_ABSTRACT
typedef std::numeric_limits<T> limits; // No fix for SF:1358600.
#else
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
boost::is_abstract<T>
, std::numeric_limits<lcast_abstract_stub>
, std::numeric_limits<T>
>::type limits;
#endif
bool const use_default_precision =
!limits::is_specialized || limits::is_exact;
if(!use_default_precision)
{ // Includes all built-in floating-point types, float, double ...
// and UDT types for which digits (significand bits) is defined (not zero)
bool const is_specialized_bin =
limits::radix == 2 && limits::digits > 0;
bool const is_specialized_dec =
limits::radix == 10 && limits::digits10 > 0;
std::streamsize const streamsize_max =
(boost::integer_traits<std::streamsize>::max)();
if(is_specialized_bin)
{ // Floating-point types with
// limits::digits defined by the specialization.
unsigned long const digits = limits::digits;
unsigned long const precision = 2UL + digits * 30103UL / 100000UL;
// unsigned long is selected because it is at least 32-bits
// and thus ULONG_MAX / 30103UL is big enough for all types.
BOOST_ASSERT(
digits < ULONG_MAX / 30103UL &&
precision > limits::digits10 + 0UL &&
precision <= streamsize_max + 0UL
);
return precision;
}
else if(is_specialized_dec)
{ // Decimal Floating-point type, most likely a User Defined Type
// rather than a real floating-point hardware type.
unsigned int const precision = limits::digits10 + 1U;
BOOST_ASSERT(precision <= streamsize_max + 0UL);
return precision;
}
}
// Integral type (for which precision has no effect)
// or type T for which limits is NOT specialized,
// so assume stream precision remains the default 6 decimal digits.
// Warning: if your User-defined Floating-point type T is NOT specialized,
// then you may lose accuracy by only using 6 decimal digits.
// To avoid this, you need to specialize T with either
// radix == 2 and digits == the number of significand bits,
// OR
// radix = 10 and digits10 == the number of decimal digits.
return 6;
#endif
}
template<class T>
inline void lcast_set_precision(std::ios_base& stream, T*)
{
stream.precision(lcast_get_precision<T>());
}
template<class Source, class Target>
inline void lcast_set_precision(std::ios_base& stream, Source*, Target*)
{
std::streamsize const s = lcast_get_precision(static_cast<Source*>(0));
std::streamsize const t = lcast_get_precision(static_cast<Target*>(0));
stream.precision(s > t ? s : t);
}
}}
#endif // BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
Regular → Executable
+7 -1
View File
@@ -23,7 +23,13 @@ inline T implicit_cast (typename mpl::identity<T>::type x) {
//template <typename T>
//void implicit_cast (...);
// Macro for when you need a constant expression (Gennaro Prota)
#define BOOST_IMPLICIT_CAST(dst_type, expr) \
( sizeof( implicit_cast<dst_type>(expr) ) \
, \
static_cast<dst_type>(expr) \
)
} // namespace boost
#endif // IMPLICIT_CAST_DWA200356_HPP
File diff suppressed because it is too large Load Diff
+6 -5
View File
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Boost Conversion Library</title>
</head>
@@ -22,17 +22,18 @@ supplied by several headers:</p>
<ul>
<li>The <a href="cast.htm">boost/cast</a> header provides <b>polymorphic_cast&lt;&gt;</b>
and <b>polymorphic_downcast&lt;&gt;</b> to perform safe casting between
polymorphic types.<br>
polymorphic types, and <b> numeric_cast</b><i>&lt;&gt;</i> to perform safe casting
between numeric types.<br>
</li>
<li>The <a href="../../doc/html/boost_lexical_cast.html">boost/lexical_cast</a> header provides <b>lexical_cast&lt;&gt;</b>
<li>The <a href="lexical_cast.htm">boost/lexical_cast</a> header provides <b>lexical_cast&lt;&gt;</b>
general literal text conversions, such as an <code>int</code> represented as
a <code>string</code>, or vice-versa.</li>
</ul>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED"
S-Format="%d %B, %Y" startspan -->June 23, 2005<!--webbot bot="Timestamp" endspan i-checksum="30348" -->
S-Format="%d %B, %Y" startspan -->06 January, 2001<!--webbot bot="Timestamp" endspan i-checksum="38320" -->
</p>
</body>
</html>
</html>
+221 -14
View File
@@ -1,16 +1,223 @@
<!--
Copyright 2005-2007 Daniel James.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-->
<!-- saved from url=(0022)http://internet.e-mail -->
<!doctype html public "-//W3C//DTD HTML Transitional 4.0//EN">
<html>
<head>
<meta http-equiv="refresh" content="0; URL=../../doc/html/boost_lexical_cast.html">
</head>
<body>
Automatic redirection failed, please go to
<a href="../../doc/html/boost_lexical_cast.html">../../doc/html/boost_lexical_cast.html</a>
</body>
<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="../../boost.png" alt="boost.png (6897 bytes)" align="center" width="277" height="86">Header
<a href="../../boost/lexical_cast.hpp">boost/lexical_cast.hpp</a></h1>
<ul type="square">
<li>
<a href="#motivation">Motivation</a></li>
<li>
<a href="#examples">Examples</a></li>
<li>
<a href="#synopsis">Synopsis</a></li>
<li>
<a href="#lexical_cast"><code>lexical_cast</code></a></li>
<li>
<a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a></li>
<li>
<a href="#changes">Changes</a></li>
</ul>
<hr>
<h2><a name="motivation">Motivation</a></h2>
Sometimes a value must be converted to a literal text form, such as an <code>int</code>
represented as a <code>string</code>, or vice-versa, when a <code>string</code>
is interpreted as an <code>int</code>. Such examples are common when converting
between data types internal to a program and representation external to a
program, such as windows and configuration files.
<p>
The standard C and C++ libraries offer a number of facilities for performing
such conversions. However, they vary with their ease of use, extensibility, and
safety.
<p>
For instance, there are a number of limitations with the family of standard C
functions typified by <code>atoi</code>:
<ul type="square">
<li>
Conversion is supported in one direction only: from text to internal data type.
Converting the other way using the C library requires either the inconvenience
and compromised safety of the <code>sprintf</code> function, or the loss of
portability associated with non-standard functions such as <code>itoa</code>.
</li>
<li>
The range of types supported is only a subset of the built-in numeric types,
namely <code>int</code>, <code>long</code>, and <code>double</code>.
</li>
<li>
The range of types cannot be extended in a uniform manner. For instance,
conversion from string representation to <code>complex</code> or <code>rational</code>.
</li>
</ul>
The standard C functions typified by <code>strtol</code> have the same basic
limitations, but offer finer control over the conversion process. However, for
the common case such control is often either not required or not used. The <code>scanf</code>
family of functions offer even greater control, but also lack safety and ease
of use.
<p>
The standard C++ library offers <code>stringstream</code> for the kind of
in-core formatting being discussed. It offers a great deal of control over the
formatting and conversion of I/O to and from arbitrary types through text.
However, for simple conversions direct use of <code>stringstream</code> can be
either clumsy (with the introduction of extra local variables and the loss of
infix-expression convenience) or obscure (where <code>stringstream</code>
objects are created as temporary objects in an expression). Facets provide a
comprehensive concept and facility for controlling textual representation, but
their perceived complexity and high entry level requires an extreme degree of
involvement for simple conversions, and excludes all but a few programmers.
<p>
The <code>lexical_cast</code> function template offers a convenient and
consistent form for supporting common conversions to and from arbitrary types
when they are represented as text. The simplification it offers is in
expression-level convenience for such conversions. For more involved
conversions, such as where precision or formatting need tighter control than is
offered by the default behavior of <code>lexical_cast</code>, the conventional <code>
stringstream</code> approach is recommended. Where the conversions are
numeric to numeric, <code><a href="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>
int main(int argc, char * argv[])
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
std::vector&lt;short&gt; args;
while(*++argv)
{
try
{
args.push_back(lexical_cast&lt;short&gt;(*argv));
}
catch(bad_lexical_cast &amp;)
{
args.push_back(0);
}
}
...
}
</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)
{
log_message(&quot;Error &quot; + boost::lexical_cast&lt;std::string&gt;(yoko) + &quot;: &quot; + strerror(yoko));
}
</pre>
</blockquote>
<hr>
<h2><a name="synopsis">Synopsis</a></h2>
Library features defined in <a href="../../boost/lexical_cast.hpp"><code>&quot;boost/lexical_cast.hpp&quot;</code></a>:
<blockquote>
<pre>
namespace boost
{
class <a href="#bad_lexical_cast">bad_lexical_cast</a>;
template&lt;typename Target, typename Source&gt;
Target <a href="#lexical_cast">lexical_cast</a>(Source arg);
}
</pre>
</blockquote>Unit test defined in <a href="lexical_cast_test.cpp"><code>&quot;lexical_cast_test.cpp&quot;</code></a>.
<p>
<hr>
<h2><a name="lexical_cast"><code>lexical_cast</code></a></h2>
<blockquote>
<pre>
template&lt;typename Target, typename Source&gt;
Target lexical_cast(Source arg);
</pre>
</blockquote>Returns the result of streaming <code>arg</code> into a
standard library string-based stream and then out as a <code>Target</code> object.
Where <code>Target</code> is either <code>std::string</code>
or <code>std::wstring</code>, stream extraction takes the whole content
of the string, including spaces, rather than relying on the default
<code>operator&gt;&gt;</code> behavior.
If the conversion is unsuccessful, a <a href="#bad_lexical_cast">
<code>bad_lexical_cast</code></a> exception is thrown.
<p>
The requirements on the argument and result types are:
<ul type="square">
<li>
<code>Source</code> is <i>OutputStreamable</i>, meaning that an <code>operator&lt;&lt;</code>
is defined that takes a <code>std::ostream</code> or <code>std::wostream</code> object on the
left hand side and an instance of the argument type on the right.
</li>
<li>
<code>Target</code> is <i>InputStreamable</i>, meaning that an <code>operator&gt;&gt;</code>
is defined that takes a <code>std::istream</code> or <code>std::wistream</code> object on the left hand side
and an instance of the result type on the right.
</li>
<li>
Both <code>Source</code> and <code>Target</code> are <i>CopyConstructible</i> [20.1.3].
</li>
<li>
<code>Target</code> is <i>DefaultConstructible</i>, meaning that it is possible
to <i>default-initialize</i> an object of that type [8.5, 20.1.4].
</li>
</ul>
The character type of the underlying stream is assumed to be <code>char</code> unless
either the <code>Source</code> or the <code>Target</code> requires wide-character
streaming, in which case the underlying stream uses <code>wchar_t</code>.
<code>Source</code> types that require wide-character streaming are <code>wchar_t</code>,
<code>wchar_t *</code>, and <code>std::wstring</code>. <code>Target</code> types that
require wide-character streaming are <code>wchar_t</code> and <code>std::wstring</code>.
<p>
Where a higher degree of control is required over conversions, <code>std::stringstream</code>
and <code>std::wstringstream</code> offer a more appropriate path. Where non-stream-based conversions are
required, <code>lexical_cast</code>
is the wrong tool for the job and is not special-cased for such scenarios.
<p>
<hr>
<h2><a name="bad_lexical_cast"><code>bad_lexical_cast</code></a></h2>
<blockquote>
<pre>
class bad_lexical_cast : public std::bad_cast
{
public:
... // <i>same member function interface as</i> std::exception
};
</pre>
</blockquote>Exception used to indicate runtime <a href="#lexical_cast"><code>lexical_cast</code></a>
failure.
<hr>
<h2><a name="changes">Changes</a></h2>
<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>
</html>
+85 -839
View File
File diff suppressed because it is too large Load Diff
-29
View File
@@ -1,29 +0,0 @@
#==============================================================================
# Copyright (c) 2012 Antony Polukhin
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#==============================================================================
# performance tests
import testing ;
import path ;
path-constant TEST_DIR : . ;
project performance/test
: source-location ./
: requirements
# <library>/boost/chrono//boost_chrono
# <library>/boost/system//boost_system
<link>static
<target-os>freebsd:<linkflags>"-lrt"
<target-os>linux:<linkflags>"-lrt"
<toolset>gcc:<cxxflags>-fvisibility=hidden
<toolset>intel-linux:<cxxflags>-fvisibility=hidden
<toolset>sun:<cxxflags>-xldscope=hidden
: default-build release
;
run performance_test.cpp : $(TEST_DIR) ;
-324
View File
@@ -1,324 +0,0 @@
// (C) Copyright Antony Polukhin 2012.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/config for most recent version.
//
// Testing lexical_cast<> performance
//
#define BOOST_ERROR_CODE_HEADER_ONLY
#define BOOST_CHRONO_HEADER_ONLY
#include <boost/lexical_cast.hpp>
#include <boost/chrono.hpp>
#include <fstream>
#include <cstring>
#include <boost/container/string.hpp>
// File to output data
std::fstream fout;
template <class OutT, class InT>
static inline void test_lexical(const InT& in_val) {
OutT out_val = boost::lexical_cast<OutT>(in_val);
(void)out_val;
}
template <class OutT, class InT>
static inline void test_ss_constr(const InT& in_val) {
OutT out_val;
std::stringstream ss;
ss << in_val;
if (ss.fail()) throw std::logic_error("descr");
ss >> out_val;
if (ss.fail()) throw std::logic_error("descr");
}
template <class OutT, class StringStreamT, class InT>
static inline void test_ss_noconstr(StringStreamT& ss, const InT& in_val) {
OutT out_val;
ss << in_val; // ss is an instance of std::stringstream
if (ss.fail()) throw std::logic_error("descr");
ss >> out_val;
if (ss.fail()) throw std::logic_error("descr");
/* reseting std::stringstream to use it again */
ss.str(std::string());
ss.clear();
}
struct structure_sprintf {
template <class OutT, class BufferT, class InT>
static inline void test(BufferT* buffer, const InT& in_val, const char* const conv) {
sprintf(buffer, conv, in_val);
OutT out_val(buffer);
}
template <class OutT, class BufferT>
static inline void test(BufferT* buffer, const std::string& in_val, const char* const conv) {
sprintf(buffer, conv, in_val.c_str());
OutT out_val(buffer);
}
};
struct structure_sscanf {
template <class OutT, class BufferT, class InT>
static inline void test(BufferT* /*buffer*/, const InT& in_val, const char* const conv) {
OutT out_val;
sscanf(reinterpret_cast<const char*>(in_val), conv, &out_val);
}
template <class OutT, class BufferT>
static inline void test(BufferT* /*buffer*/, const std::string& in_val, const char* const conv) {
OutT out_val;
sscanf(in_val.c_str(), conv, &out_val);
}
template <class OutT, class BufferT>
static inline void test(BufferT* /*buffer*/, const boost::iterator_range<const char*>& in_val, const char* const conv) {
OutT out_val;
sscanf(in_val.begin(), conv, &out_val);
}
};
struct structure_fake {
template <class OutT, class BufferT, class InT>
static inline void test(BufferT* /*buffer*/, const InT& /*in_val*/, const char* const /*conv*/) {}
};
static const int fake_test_value = 9999;
template <class T>
static inline void min_fancy_output(T v1, T v2, T v3, T v4) {
const char beg_mark[] = "!!! *";
const char end_mark[] = "* !!!";
const char no_mark[] = "";
unsigned int res = 4;
if (v1 < v2 && v1 < v3 && v1 < v4) res = 1;
if (v2 < v1 && v2 < v3 && v2 < v4) res = 2;
if (v3 < v1 && v3 < v2 && v3 < v4) res = 3;
fout << "[ "
<< (res == 1 ? beg_mark : no_mark)
;
if (v1) fout << v1;
else fout << "<1";
fout << (res == 1 ? end_mark : no_mark)
<< " ][ "
<< (res == 2 ? beg_mark : no_mark)
;
if (v2) fout << v2;
else fout << "<1";
fout << (res == 2 ? end_mark : no_mark)
<< " ][ "
<< (res == 3 ? beg_mark : no_mark)
;
if (v3) fout << v3;
else fout << "<1";
fout << (res == 3 ? end_mark : no_mark)
<< " ][ "
<< (res == 4 ? beg_mark : no_mark)
;
if (!v4) fout << "<1";
else if (v4 == fake_test_value) fout << "---";
else fout << v4;
fout
<< (res == 4 ? end_mark : no_mark)
<< " ]";
}
template <unsigned int IetartionsCountV, class ToT, class SprintfT, class FromT>
static inline void perf_test_impl(const FromT& in_val, const char* const conv) {
typedef boost::chrono::steady_clock test_clock;
test_clock::time_point start;
typedef boost::chrono::milliseconds duration_t;
duration_t lexical_cast_time, ss_constr_time, ss_noconstr_time, printf_time;
start = test_clock::now();
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
test_lexical<ToT>(in_val);
test_lexical<ToT>(in_val);
test_lexical<ToT>(in_val);
test_lexical<ToT>(in_val);
}
lexical_cast_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
start = test_clock::now();
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
test_ss_constr<ToT>(in_val);
test_ss_constr<ToT>(in_val);
test_ss_constr<ToT>(in_val);
test_ss_constr<ToT>(in_val);
}
ss_constr_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
std::stringstream ss;
start = test_clock::now();
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
test_ss_noconstr<ToT>(ss, in_val);
test_ss_noconstr<ToT>(ss, in_val);
test_ss_noconstr<ToT>(ss, in_val);
test_ss_noconstr<ToT>(ss, in_val);
}
ss_noconstr_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
char buffer[128];
start = test_clock::now();
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
SprintfT::template test<ToT>(buffer, in_val, conv);
SprintfT::template test<ToT>(buffer, in_val, conv);
SprintfT::template test<ToT>(buffer, in_val, conv);
SprintfT::template test<ToT>(buffer, in_val, conv);
}
printf_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
min_fancy_output(
lexical_cast_time.count(),
ss_constr_time.count(),
ss_noconstr_time.count(),
boost::is_same<SprintfT, structure_fake>::value ? fake_test_value : printf_time.count()
);
}
template <class ToT, class SprintfT, class FromT>
static inline void perf_test(const std::string& test_name, const FromT& in_val, const char* const conv) {
const unsigned int ITERATIONSCOUNT = 100000;
fout << " [[ " << test_name << " ]";
perf_test_impl<ITERATIONSCOUNT/4, ToT, SprintfT>(in_val, conv);
fout << "]\n";
}
template <class ConverterT>
void string_like_test_set(const std::string& from) {
typedef structure_sscanf ssc_t;
ConverterT conv;
perf_test<char, ssc_t>(from + "->char", conv("c"), "%c");
perf_test<signed char, ssc_t>(from + "->signed char", conv("c"), "%hhd");
perf_test<unsigned char, ssc_t>(from + "->unsigned char", conv("c"), "%hhu");
perf_test<int, ssc_t>(from + "->int", conv("100"), "%d");
perf_test<short, ssc_t>(from + "->short", conv("100"), "%hd");
perf_test<long int, ssc_t>(from + "->long int", conv("100"), "%ld");
perf_test<boost::long_long_type, ssc_t>(from + "->long long", conv("100"), "%lld");
perf_test<unsigned int, ssc_t>(from + "->unsigned int", conv("100"), "%u");
perf_test<unsigned short, ssc_t>(from + "->unsigned short", conv("100"), "%hu");
perf_test<unsigned long int, ssc_t>(from + "->unsigned long int", conv("100"), "%lu");
perf_test<boost::ulong_long_type, ssc_t>(from + "->unsigned long long", conv("100"), "%llu");
// perf_test<bool, ssc_t>(from + "->bool", conv("1"), "%");
perf_test<float, ssc_t>(from + "->float", conv("1.123"), "%f");
perf_test<double, ssc_t>(from + "->double", conv("1.123"), "%lf");
perf_test<long double, ssc_t>(from + "->long double", conv("1.123"), "%Lf");
perf_test<std::string, structure_fake>(from + "->string", conv("string"), "%Lf");
perf_test<boost::container::string, structure_fake>(from + "->container::string"
, conv("string"), "%Lf");
}
struct to_string_conv {
std::string operator()(const char* const c) const {
return c;
}
};
struct to_char_conv {
const char* operator()(const char* const c) const {
return c;
}
};
struct to_uchar_conv {
const unsigned char* operator()(const char* const c) const {
return reinterpret_cast<const unsigned char*>(c);
}
};
struct to_schar_conv {
const signed char* operator()(const char* const c) const {
return reinterpret_cast<const signed char*>(c);
}
};
struct to_iterator_range {
boost::iterator_range<const char*> operator()(const char* const c) const {
return boost::make_iterator_range(c, c + std::strlen(c));
}
};
int main(int argc, char** argv) {
BOOST_ASSERT(argc >= 2);
std::string output_path(argv[1]);
output_path += "/results.txt";
fout.open(output_path.c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
BOOST_ASSERT(fout);
fout << "[section " << BOOST_COMPILER << "]\n"
<< "[table:id Performance Table ( "<< BOOST_COMPILER << ")\n"
<< "[[From->To] [lexical_cast] [std::stringstream with construction] "
<< "[std::stringstream without construction][scanf/printf]]\n";
// From std::string to ...
string_like_test_set<to_string_conv>("string");
// From ... to std::string
perf_test<std::string, structure_sprintf>("string->char", 'c', "%c");
perf_test<std::string, structure_sprintf>("string->signed char", static_cast<signed char>('c'), "%hhd");
perf_test<std::string, structure_sprintf>("string->unsigned char", static_cast<unsigned char>('c'), "%hhu");
perf_test<std::string, structure_sprintf>("int->string", 100, "%d");
perf_test<std::string, structure_sprintf>("short->string", static_cast<short>(100), "%hd");
perf_test<std::string, structure_sprintf>("long int->string", 100l, "%ld");
perf_test<std::string, structure_sprintf>("long long->string", 100ll, "%lld");
perf_test<std::string, structure_sprintf>("unsigned int->string", static_cast<unsigned short>(100u), "%u");
perf_test<std::string, structure_sprintf>("unsigned short->string", 100u, "%hu");
perf_test<std::string, structure_sprintf>("unsigned long int->string", 100ul, "%lu");
perf_test<std::string, structure_sprintf>("unsigned long long->string", static_cast<boost::ulong_long_type>(100), "%llu");
// perf_test<bool, structure_sscanf>("bool->string", std::string("1"), "%");
perf_test<std::string, structure_sprintf>("float->string", 1.123f, "%f");
perf_test<std::string, structure_sprintf>("double->string", 1.123, "%lf");
perf_test<std::string, structure_sprintf>("long double->string", 1.123L, "%Lf");
string_like_test_set<to_char_conv>("char*");
string_like_test_set<to_uchar_conv>("unsigned char*");
string_like_test_set<to_schar_conv>("signed char*");
string_like_test_set<to_iterator_range>("iterator_range<char*>");
perf_test<int, structure_fake>("int->int", 100, "");
perf_test<double, structure_fake>("float->double", 100.0f, "");
perf_test<signed char, structure_fake>("char->signed char", 'c', "");
fout << "]\n"
<< "[endsect]\n\n";
return 0;
}
+34
View File
@@ -0,0 +1,34 @@
# Signals library
# Copyright (C) 2001-2003 Douglas Gregor
# Permission to copy, use, sell and distribute this software is granted
# provided this copyright notice appears in all copies. Permission to modify
# the code and to distribute modified code is granted provided this copyright
# notice appears in all copies, and a notice that the code was modified is
# included with the copyright notice. This software is provided "as is"
# without express or implied warranty, and with no claim as to its suitability
# for any purpose.
# For more information, see http://www.boost.org/
# Testing Jamfile autogenerated from XML source
subproject libs/conversion/test ;
# bring in rules for testing
import testing ;
# Make tests run by default.
DEPENDS all : test ;
{
test-suite conversion
: [ run implicit_cast.cpp ]
[ compile-fail implicit_cast_fail.cpp ]
[ run ../cast_test.cpp ]
[ run ../numeric_cast_test.cpp ]
[ run ../lexical_cast_test.cpp ]
;
}
+14 -40
View File
@@ -1,51 +1,25 @@
# Signals library
# Copyright (C) 2001-2003 Douglas Gregor
# Copyright (C) 2011-2012 Antony Polukhin
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
# Permission to copy, use, sell and distribute this software is granted
# provided this copyright notice appears in all copies. Permission to modify
# the code and to distribute modified code is granted provided this copyright
# notice appears in all copies, and a notice that the code was modified is
# included with the copyright notice. This software is provided "as is"
# without express or implied warranty, and with no claim as to its suitability
# for any purpose.
# For more information, see http://www.boost.org/
# bring in rules for testing
import testing ;
import feature ;
project
: requirements
<library>/boost/test//boost_unit_test_framework
<link>static
<toolset>gcc-4.8:<define>BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES
;
# Thanks to Steven Watanabe for helping with <nowchar> feature
feature.feature nowchar : on :
composite optional propagated link-incompatible ;
feature.compose <nowchar>on : <cxxflags>/Zc:wchar_t- ;
test-suite conversion
: [ run implicit_cast.cpp ]
[ compile-fail implicit_cast_fail.cpp ]
[ run ../cast_test.cpp ]
[ run ../numeric_cast_test.cpp ]
[ run ../lexical_cast_test.cpp ]
[ run lexical_cast_loopback_test.cpp ]
[ run lexical_cast_abstract_test.cpp ]
[ run lexical_cast_noncopyable_test.cpp ]
[ run lexical_cast_vc8_bug_test.cpp ]
[ run lexical_cast_wchars_test.cpp ]
[ run lexical_cast_float_types_test.cpp ]
[ run lexical_cast_inf_nan_test.cpp ]
[ run lexical_cast_containers_test.cpp ]
[ run lexical_cast_empty_input_test.cpp ]
[ run lexical_cast_pointers_test.cpp ]
[ compile lexical_cast_typedefed_wchar_test.cpp : <toolset>msvc:<nowchar>on ]
[ run lexical_cast_typedefed_wchar_test_runtime.cpp : : : <toolset>msvc:<nowchar>on <toolset>msvc,<stdlib>stlport:<build>no ]
[ run lexical_cast_no_locale_test.cpp : : : <define>BOOST_NO_STD_LOCALE <define>BOOST_LEXICAL_CAST_ASSUME_C_LOCALE ]
[ run lexical_cast_no_exceptions_test.cpp : : : <define>BOOST_NO_EXCEPTIONS
<toolset>gcc-4.3:<cflags>-fno-exceptions
<toolset>gcc-4.4:<cflags>-fno-exceptions
<toolset>gcc-4.5:<cflags>-fno-exceptions
<toolset>gcc-4.6:<cflags>-fno-exceptions
<toolset>gcc-4.7:<cflags>-fno-exceptions
]
[ run lexical_cast_iterator_range_test.cpp ]
;
+4 -9
View File
@@ -4,8 +4,9 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/implicit_cast.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cassert>
#include <boost/type.hpp>
using boost::implicit_cast;
using boost::type;
@@ -24,15 +25,9 @@ typedef type<foo> foo_type;
int main()
{
type<long> x = check_return(boost::implicit_cast<long>(1));
BOOST_TEST(boost::implicit_cast<long>(1) == 1L);
assert(boost::implicit_cast<long>(1) == 1L);
type<foo> f = check_return(boost::implicit_cast<foo>("hello"));
type<long> z = check_return(boost::implicit_cast<long>(foo("hello")));
// warning supression:
(void)x;
(void)f;
(void)z;
return boost::report_errors();
return 0;
}
-61
View File
@@ -1,61 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Sergey Shandar 2005, Alexander Nasonov, 2007.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
//
// Test abstract class. Bug 1358600:
// http://sf.net/tracker/?func=detail&aid=1358600&group_id=7586&atid=107586
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
using namespace boost;
void test_abstract();
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast unit test");
suite->add(BOOST_TEST_CASE(&test_abstract));
return suite;
}
class A
{
public:
virtual void out(std::ostream &) const = 0;
};
class B: public A
{
public:
virtual void out(std::ostream &O) const { O << "B"; }
};
std::ostream &operator<<(std::ostream &O, const A &a)
{
a.out(O);
return O;
}
void test_abstract()
{
const A &a = B();
BOOST_CHECK(boost::lexical_cast<std::string>(a) == "B");
}
-83
View File
@@ -1,83 +0,0 @@
// Testing boost::lexical_cast with boost::container::string.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/container/string.hpp>
void testing_boost_containers_basic_string();
void testing_boost_containers_string_std_string();
void testing_boost_containers_string_widening();
using namespace boost;
boost::unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("Testing boost::lexical_cast with boost::container::string");
suite->add(BOOST_TEST_CASE(testing_boost_containers_basic_string));
suite->add(BOOST_TEST_CASE(testing_boost_containers_string_std_string));
suite->add(BOOST_TEST_CASE(testing_boost_containers_string_widening));
return suite;
}
void testing_boost_containers_basic_string()
{
BOOST_CHECK("100" == lexical_cast<boost::container::string>("100"));
BOOST_CHECK(L"100" == lexical_cast<boost::container::wstring>(L"100"));
BOOST_CHECK("100" == lexical_cast<boost::container::string>(100));
boost::container::string str("1000");
BOOST_CHECK(1000 == lexical_cast<int>(str));
}
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
#endif
void testing_boost_containers_string_std_string()
{
std::string std_str("std_str");
boost::container::string boost_str("boost_str");
BOOST_CHECK(boost::lexical_cast<std::string>(boost_str) == "boost_str");
BOOST_CHECK(boost::lexical_cast<boost::container::string>(std_str) == "std_str");
#ifndef BOOST_LCAST_NO_WCHAR_T
std::wstring std_wstr(L"std_wstr");
boost::container::wstring boost_wstr(L"boost_wstr");
BOOST_CHECK(boost::lexical_cast<std::wstring>(boost_wstr) == L"boost_wstr");
BOOST_CHECK(boost::lexical_cast<boost::container::wstring>(std_wstr) == L"std_wstr");
#endif
}
void testing_boost_containers_string_widening()
{
const char char_array[] = "Test string";
#ifndef BOOST_LCAST_NO_WCHAR_T
const wchar_t wchar_array[] = L"Test string";
BOOST_CHECK(boost::lexical_cast<boost::container::wstring>(char_array) == wchar_array);
#endif
#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
const char16_t char16_array[] = u"Test string";
BOOST_CHECK(boost::lexical_cast<boost::container::basic_string<char16_t> >(char_array) == char16_array);
#endif
#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
const char32_t char32_array[] = U"Test string";
BOOST_CHECK(boost::lexical_cast<boost::container::basic_string<char32_t> >(char_array) == char32_array);
#endif
}
-165
View File
@@ -1,165 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/range/iterator_range.hpp>
using namespace boost;
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
#endif
template <class T>
void do_test_on_empty_input(T& v)
{
BOOST_CHECK_THROW(lexical_cast<int>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<float>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<double>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<long double>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned int>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned short>(v), bad_lexical_cast);
#if defined(BOOST_HAS_LONG_LONG)
BOOST_CHECK_THROW(lexical_cast<boost::ulong_long_type>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<boost::long_long_type>(v), bad_lexical_cast);
#elif defined(BOOST_HAS_MS_INT64)
BOOST_CHECK_THROW(lexical_cast<unsigned __int64>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<__int64>(v), bad_lexical_cast);
#endif
}
void test_empty_iterator_range()
{
boost::iterator_range<char*> v;
do_test_on_empty_input(v);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(v), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
boost::iterator_range<const char*> cv;
do_test_on_empty_input(cv);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(cv), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(cv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(cv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(cv), bad_lexical_cast);
const boost::iterator_range<const char*> ccv;
do_test_on_empty_input(ccv);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(ccv), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(ccv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(ccv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(ccv), bad_lexical_cast);
}
void test_empty_string()
{
std::string v;
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
#ifndef BOOST_LCAST_NO_WCHAR_T
std::wstring vw;
do_test_on_empty_input(vw);
BOOST_CHECK_THROW(lexical_cast<wchar_t>(vw), bad_lexical_cast);
#endif
// Currently, no compiler and STL library fully support char16_t and char32_t
//#ifndef BOOST_NO_CHAR16_T
// std::basic_string<char16_t> v16w;
// do_test_on_empty_input(v16w);
// BOOST_CHECK_THROW(lexical_cast<char16_t>(v16w), bad_lexical_cast);
//#endif
//#ifndef BOOST_NO_CHAR32_T
// std::basic_string<char32_t> v32w;
// do_test_on_empty_input(v32w);
// BOOST_CHECK_THROW(lexical_cast<char32_t>(v32w), bad_lexical_cast);
//#endif
}
struct Escape
{
Escape(const std::string& s)
: str_(s)
{}
std::string str_;
};
inline std::ostream& operator<< (std::ostream& o, const Escape& rhs)
{
return o << rhs.str_;
}
void test_empty_user_class()
{
Escape v("");
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
}
namespace std {
inline std::ostream & operator<<(std::ostream & out, const std::vector<long> & v)
{
std::ostream_iterator<long> it(out);
std::copy(v.begin(), v.end(), it);
assert(out);
return out;
}
}
void test_empty_vector()
{
std::vector<long> v;
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
}
struct my_string {
friend std::ostream &operator<<(std::ostream& sout, my_string const&/* st*/) {
return sout << "";
}
};
void test_empty_zero_terminated_string()
{
my_string st;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(st), std::string());;
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast. Empty input unit test");
suite->add(BOOST_TEST_CASE(&test_empty_iterator_range));
suite->add(BOOST_TEST_CASE(&test_empty_string));
suite->add(BOOST_TEST_CASE(&test_empty_user_class));
suite->add(BOOST_TEST_CASE(&test_empty_vector));
suite->add(BOOST_TEST_CASE(&test_empty_zero_terminated_string));
return suite;
}
-515
View File
@@ -1,515 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/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/cstdint.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
void test_conversion_from_to_float();
void test_conversion_from_to_double();
void test_conversion_from_to_long_double();
using namespace boost;
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast float types unit test");
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_float));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_double));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long_double));
return suite;
}
// Replace "-,999" with "-999".
template<class CharT>
std::basic_string<CharT> to_str_gcc_workaround(std::basic_string<CharT> str)
{
std::locale loc;
std::numpunct<CharT> const& np = BOOST_USE_FACET(std::numpunct<CharT>, loc);
std::ctype<CharT> const& ct = BOOST_USE_FACET(std::ctype<CharT>, loc);
if(np.grouping().empty())
return str;
CharT prefix[3] = { ct.widen('-'), np.thousands_sep(), CharT() };
if(str.find(prefix) != 0)
return str;
prefix[1] = CharT();
str.replace(0, 2, prefix);
return str;
}
template<class CharT, class T>
std::basic_string<CharT> to_str(T t)
{
std::basic_ostringstream<CharT> o;
o << t;
return to_str_gcc_workaround(o.str());
}
template<class T>
void test_conversion_from_to_float_for_locale()
{
std::locale current_locale;
typedef std::numpunct<char> numpunct;
numpunct const& np = BOOST_USE_FACET(numpunct, current_locale);
if ( !np.grouping().empty() )
{
BOOST_CHECK_THROW(
lexical_cast<T>( std::string("100") + np.thousands_sep() + np.thousands_sep() + "0" )
, bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( std::string("100") + np.thousands_sep() ), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( np.thousands_sep() + std::string("100") ), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( std::string("1") + np.thousands_sep() + np.decimal_point() + "e10" ), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( std::string("1e10") + np.thousands_sep() ), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( std::string("1") + np.thousands_sep() + "e10" ), bad_lexical_cast);
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< char >(100000) ), 100000, (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< char >(10000000u) ), 10000000u, (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< char >(100) ), 100, (std::numeric_limits<T>::epsilon()) );
#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< wchar_t >(100000) ), 100000, (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< wchar_t >(10000000u) ), 10000000u, (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< wchar_t >(100) ), 100, (std::numeric_limits<T>::epsilon()) );
#endif
// Exception must not be thrown, when we are using no separators at all
BOOST_CHECK_CLOSE_FRACTION( lexical_cast<T>("30000"), static_cast<T>(30000), (std::numeric_limits<T>::epsilon()) );
}
}
/*
* Converts char* [and wchar_t] to float number type and checks, that generated
* number is in interval [base_value-epsilon, base_value+epsilon].
*/
#ifndef BOOST_LCAST_NO_WCHAR_T
#define CHECK_CLOSE_ABS_DIFF(VAL,PREFIX) \
converted_val = lexical_cast<test_t>(#VAL); \
BOOST_CHECK_CLOSE_FRACTION( (VAL ## L? VAL ## L : std::numeric_limits<test_t>::epsilon()), \
(converted_val ? converted_val : std::numeric_limits<test_t>::epsilon()), \
std::numeric_limits<test_t>::epsilon() \
); \
BOOST_CHECK_EQUAL(converted_val, lexical_cast<test_t>(L## #VAL) );
#else
#define CHECK_CLOSE_ABS_DIFF(VAL,TYPE) \
converted_val = lexical_cast<test_t>(#VAL); \
BOOST_CHECK_CLOSE_FRACTION( (VAL ## L? VAL ## L : std::numeric_limits<test_t>::epsilon()), \
(converted_val ? converted_val : std::numeric_limits<test_t>::epsilon()), \
std::numeric_limits<test_t>::epsilon() \
);
#endif
template <class TestType>
void test_converion_to_float_types()
{
typedef TestType test_t;
test_t converted_val;
BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<test_t>('1'), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_EQUAL(0.0, lexical_cast<test_t>('0'));
unsigned char const uc_one = '1';
unsigned char const uc_zero ='0';
BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<test_t>(uc_one), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_EQUAL(0.0, lexical_cast<test_t>(uc_zero));
signed char const sc_one = '1';
signed char const sc_zero ='0';
BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<test_t>(sc_one), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_EQUAL(0.0, lexical_cast<test_t>(sc_zero));
BOOST_CHECK_CLOSE_FRACTION(1e34L, lexical_cast<test_t>( "10000000000000000000000000000000000"), (std::numeric_limits<test_t>::epsilon()) );
// VC failes the next test
// BOOST_CHECK_CLOSE_FRACTION(1e-35L, lexical_cast<test_t>("0.00000000000000000000000000000000001"), (std::numeric_limits<test_t>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(
0.1111111111111111111111111111111111111111111111111111111111111111111111111L
, lexical_cast<test_t>("0.1111111111111111111111111111111111111111111111111111111111111111111111111")
, (std::numeric_limits<test_t>::epsilon()) );
CHECK_CLOSE_ABS_DIFF(1,test_t);
BOOST_CHECK_EQUAL(0,lexical_cast<test_t>("0"));
CHECK_CLOSE_ABS_DIFF(-1,test_t);
CHECK_CLOSE_ABS_DIFF(1.0, test_t);
CHECK_CLOSE_ABS_DIFF(0.0, test_t);
CHECK_CLOSE_ABS_DIFF(-1.0,test_t);
CHECK_CLOSE_ABS_DIFF(1e1, test_t);
CHECK_CLOSE_ABS_DIFF(0e1, test_t);
CHECK_CLOSE_ABS_DIFF(-1e1,test_t);
CHECK_CLOSE_ABS_DIFF(1.0e1, test_t);
CHECK_CLOSE_ABS_DIFF(0.0e1, test_t);
CHECK_CLOSE_ABS_DIFF(-1.0e1,test_t);
CHECK_CLOSE_ABS_DIFF(1e-1, test_t);
CHECK_CLOSE_ABS_DIFF(0e-1, test_t);
CHECK_CLOSE_ABS_DIFF(-1e-1,test_t);
CHECK_CLOSE_ABS_DIFF(1.0e-1, test_t);
CHECK_CLOSE_ABS_DIFF(0.0e-1, test_t);
CHECK_CLOSE_ABS_DIFF(-1.0e-1,test_t);
CHECK_CLOSE_ABS_DIFF(1E1, test_t);
CHECK_CLOSE_ABS_DIFF(0E1, test_t);
CHECK_CLOSE_ABS_DIFF(-1E1,test_t);
CHECK_CLOSE_ABS_DIFF(1.0E1, test_t);
CHECK_CLOSE_ABS_DIFF(0.0E1, test_t);
CHECK_CLOSE_ABS_DIFF(-1.0E1,test_t);
CHECK_CLOSE_ABS_DIFF(1E-1, test_t);
CHECK_CLOSE_ABS_DIFF(0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-1E-1,test_t);
CHECK_CLOSE_ABS_DIFF(1.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(0.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-1.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(10.0, test_t);
CHECK_CLOSE_ABS_DIFF(00.0, test_t);
CHECK_CLOSE_ABS_DIFF(-10.0,test_t);
CHECK_CLOSE_ABS_DIFF(10e1, test_t);
CHECK_CLOSE_ABS_DIFF(00e1, test_t);
CHECK_CLOSE_ABS_DIFF(-10e1,test_t);
CHECK_CLOSE_ABS_DIFF(10.0e1, test_t);
CHECK_CLOSE_ABS_DIFF(00.0e1, test_t);
CHECK_CLOSE_ABS_DIFF(-10.0e1,test_t);
CHECK_CLOSE_ABS_DIFF(10e-1, test_t);
CHECK_CLOSE_ABS_DIFF(00e-1, test_t);
CHECK_CLOSE_ABS_DIFF(-10e-1,test_t);
CHECK_CLOSE_ABS_DIFF(10.0e-1, test_t);
CHECK_CLOSE_ABS_DIFF(00.0e-1, test_t);
CHECK_CLOSE_ABS_DIFF(-10.0e-1,test_t);
CHECK_CLOSE_ABS_DIFF(10E1, test_t);
CHECK_CLOSE_ABS_DIFF(00E1, test_t);
CHECK_CLOSE_ABS_DIFF(-10E1,test_t);
CHECK_CLOSE_ABS_DIFF(10.0E1, test_t);
CHECK_CLOSE_ABS_DIFF(00.0E1, test_t);
CHECK_CLOSE_ABS_DIFF(-10.0E1,test_t);
CHECK_CLOSE_ABS_DIFF(10E-1, test_t);
CHECK_CLOSE_ABS_DIFF(00E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-10E-1,test_t);
CHECK_CLOSE_ABS_DIFF(10.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(00.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-10.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-10101.0E-011, test_t);
CHECK_CLOSE_ABS_DIFF(-10101093, test_t);
CHECK_CLOSE_ABS_DIFF(10101093, test_t);
CHECK_CLOSE_ABS_DIFF(-.34, test_t);
CHECK_CLOSE_ABS_DIFF(.34, test_t);
CHECK_CLOSE_ABS_DIFF(.34e10, test_t);
BOOST_CHECK_THROW(lexical_cast<test_t>("-1.e"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("-1.E"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.e"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.E"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0e"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0E"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("10E"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("10e"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0e-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0E-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("10E-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("10e-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("e1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("e-1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("e-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(".e"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(".11111111111111111111111111111111111111111111111111111111111111111111ee"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(".11111111111111111111111111111111111111111111111111111111111111111111e-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("."), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("-B"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("0xB"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("0x0"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("--1.0"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0e--1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0.0"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1e1e1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0e-1e-1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(" 1.0"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0 "), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(""), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>('\0'), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>('-'), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>('.'), bad_lexical_cast);
}
template <class T>
void test_float_typess_for_overflows()
{
typedef T test_t;
test_t minvalue = (std::numeric_limits<test_t>::min)();
std::string s_min_value = lexical_cast<std::string>(minvalue);
BOOST_CHECK_CLOSE_FRACTION(minvalue, lexical_cast<test_t>(minvalue), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_CLOSE_FRACTION(minvalue, lexical_cast<test_t>(s_min_value), (std::numeric_limits<test_t>::epsilon()));
test_t maxvalue = (std::numeric_limits<test_t>::max)();
std::string s_max_value = lexical_cast<std::string>(maxvalue);
BOOST_CHECK_CLOSE_FRACTION(maxvalue, lexical_cast<test_t>(maxvalue), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_CLOSE_FRACTION(maxvalue, lexical_cast<test_t>(s_max_value), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_THROW(lexical_cast<test_t>(s_max_value+"1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(s_max_value+"9"), bad_lexical_cast);
// VC9 can fail the fllowing tests on floats and doubles when using stingstream...
BOOST_CHECK_THROW(lexical_cast<test_t>("1"+s_max_value), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("9"+s_max_value), bad_lexical_cast);
if ( is_same<test_t,float>::value )
{
BOOST_CHECK_THROW(lexical_cast<test_t>( (std::numeric_limits<double>::max)() ), bad_lexical_cast);
BOOST_CHECK(
(std::numeric_limits<double>::min)() - std::numeric_limits<test_t>::epsilon()
<= lexical_cast<test_t>( (std::numeric_limits<double>::min)() )
&& lexical_cast<test_t>( (std::numeric_limits<double>::min)() )
<= (std::numeric_limits<double>::min)() + std::numeric_limits<test_t>::epsilon()
);
}
if ( sizeof(test_t) < sizeof(long double) )
{
BOOST_CHECK_THROW(lexical_cast<test_t>( (std::numeric_limits<long double>::max)() ), bad_lexical_cast);
BOOST_CHECK(
(std::numeric_limits<long double>::min)() - std::numeric_limits<test_t>::epsilon()
<= lexical_cast<test_t>( (std::numeric_limits<long double>::min)() )
&& lexical_cast<test_t>( (std::numeric_limits<long double>::min)() )
<= (std::numeric_limits<long double>::min)() + std::numeric_limits<test_t>::epsilon()
);
}
}
#undef CHECK_CLOSE_ABS_DIFF
#define TEST_TO_FROM_CAST_AROUND_TYPED(VAL,STRING_TYPE) \
test_value = VAL + std::numeric_limits<test_t>::epsilon() * i ; \
converted_val = lexical_cast<test_t>( lexical_cast<STRING_TYPE>(test_value) ); \
BOOST_CHECK_CLOSE_FRACTION( \
test_value, \
converted_val, \
std::numeric_limits<test_t>::epsilon() \
);
/*
* For interval [ from_mult*epsilon+VAL, to_mult*epsilon+VAL ], converts float type
* numbers to string[wstring] and then back to float type, then compares initial
* values and generated.
* Step is epsilon
*/
#ifndef BOOST_LCAST_NO_WCHAR_T
# define TEST_TO_FROM_CAST_AROUND(VAL) \
for(i=from_mult; i<=to_mult; ++i) { \
TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::string) \
TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::wstring) \
}
#else
# define TEST_TO_FROM_CAST_AROUND(VAL) \
for(i=from_mult; i<=to_mult; ++i) { \
TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::string) \
}
#endif
template <class TestType>
void test_converion_from_to_float_types()
{
typedef TestType test_t;
test_t test_value;
test_t converted_val;
int i;
int from_mult = -50;
int to_mult = 50;
TEST_TO_FROM_CAST_AROUND( 0.0 );
long double val1;
for(val1 = 1.0e-10L; val1 < 1e11; val1*=10 )
TEST_TO_FROM_CAST_AROUND( val1 );
long double val2;
for(val2 = -1.0e-10L; val2 > -1e11; val2*=10 )
TEST_TO_FROM_CAST_AROUND( val2 );
from_mult = -100;
to_mult = 0;
TEST_TO_FROM_CAST_AROUND( (std::numeric_limits<test_t>::max)() );
from_mult = 0;
to_mult = 100;
TEST_TO_FROM_CAST_AROUND( (std::numeric_limits<test_t>::min)() );
}
#undef TEST_TO_FROM_CAST_AROUND
#undef TEST_TO_FROM_CAST_AROUND_TYPED
template<class T, class CharT>
void test_conversion_from_float_to_char(CharT zero)
{
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(0)) == zero + 0);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(1)) == zero + 1);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(2)) == zero + 2);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(3)) == zero + 3);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(4)) == zero + 4);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(5)) == zero + 5);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(6)) == zero + 6);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(7)) == zero + 7);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(8)) == zero + 8);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(9)) == zero + 9);
BOOST_CHECK_THROW(lexical_cast<CharT>(static_cast<T>(10)), bad_lexical_cast);
T t = (std::numeric_limits<T>::max)();
BOOST_CHECK_THROW(lexical_cast<CharT>(t), bad_lexical_cast);
}
template<class T, class CharT>
void test_conversion_from_char_to_float(CharT zero)
{
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 0)), static_cast<T>(0), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 1)), static_cast<T>(1), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 2)), static_cast<T>(2), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 3)), static_cast<T>(3), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 4)), static_cast<T>(4), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 5)), static_cast<T>(5), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 6)), static_cast<T>(6), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 7)), static_cast<T>(7), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 8)), static_cast<T>(8), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 9)), static_cast<T>(9), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_THROW(lexical_cast<T>( static_cast<CharT>(zero + 10)), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( static_cast<CharT>(zero - 1)), bad_lexical_cast);
}
struct restore_oldloc
{
std::locale oldloc;
~restore_oldloc() { std::locale::global(oldloc); }
};
template<class T>
void test_conversion_from_to_float()
{ char const zero = '0';
signed char const szero = '0';
unsigned char const uzero = '0';
test_conversion_from_float_to_char<T>(zero);
test_conversion_from_char_to_float<T>(zero);
test_conversion_from_float_to_char<T>(szero);
test_conversion_from_char_to_float<T>(szero);
test_conversion_from_float_to_char<T>(uzero);
test_conversion_from_char_to_float<T>(uzero);
#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
wchar_t const wzero = L'0';
test_conversion_from_float_to_char<T>(wzero);
test_conversion_from_char_to_float<T>(wzero);
#endif
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>("+1"), 1, std::numeric_limits<T>::epsilon());
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>("+9"), 9, std::numeric_limits<T>::epsilon());
BOOST_CHECK_THROW(lexical_cast<T>("++1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>("-+9"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>("--1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>("+-9"), bad_lexical_cast);
test_converion_to_float_types<T>();
test_float_typess_for_overflows<T>();
test_converion_from_to_float_types<T>();
typedef std::numpunct<char> numpunct;
restore_oldloc guard;
std::locale const& oldloc = guard.oldloc;
std::string grouping1 = BOOST_USE_FACET(numpunct, oldloc).grouping();
std::string grouping2(grouping1);
test_conversion_from_to_float_for_locale<T>();
try
{
std::locale newloc("");
std::locale::global(newloc);
grouping2 = BOOST_USE_FACET(numpunct, newloc).grouping();
}
catch(std::exception const& ex)
{
std::string msg("Failed to set system locale: ");
msg += ex.what();
BOOST_TEST_MESSAGE(msg);
}
if(grouping1 != grouping2)
test_conversion_from_to_float_for_locale<T>();
if(grouping1.empty() && grouping2.empty())
BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested");
}
void test_conversion_from_to_float()
{
test_conversion_from_to_float<float>();
}
void test_conversion_from_to_double()
{
test_conversion_from_to_float<double>();
}
void test_conversion_from_to_long_double()
{
test_conversion_from_to_float<long double>();
}
-201
View File
@@ -1,201 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/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/math/special_functions/sign.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
#endif
using namespace boost;
template <class T>
bool is_pos_inf(T value)
{
return (boost::math::isinf)(value) && !(boost::math::signbit)(value);
}
template <class T>
bool is_neg_inf(T value)
{
return (boost::math::isinf)(value) && (boost::math::signbit)(value);
}
template <class T>
bool is_pos_nan(T value)
{
return (boost::math::isnan)(value) && !(boost::math::signbit)(value);
}
template <class T>
bool is_neg_nan(T value)
{
/* There is some strange behaviour on Itanium platform with -nan nuber for long double.
* It is a IA64 feature, or it is a boost::math feature, not a lexical_cast bug */
#if defined(__ia64__) || defined(_M_IA64)
return (boost::math::isnan)(value)
&& ( boost::is_same<T, long double >::value || (boost::math::signbit)(value) );
#else
return (boost::math::isnan)(value) && (boost::math::signbit)(value);
#endif
}
template <class T>
void test_inf_nan_templated()
{
typedef T test_t;
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("inf") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("INF") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-inf") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-INF") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+inf") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+INF") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("infinity") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("INFINITY") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-infinity") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-INFINITY") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+infinity") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+INFINITY") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("iNfiNity") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("INfinity") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-inFINITY") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-INFINITY") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("nan") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("NAN") ) );
BOOST_CHECK( is_neg_nan( lexical_cast<test_t>("-nan") ) );
BOOST_CHECK( is_neg_nan( lexical_cast<test_t>("-NAN") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("+nan") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("+NAN") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("nAn") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("NaN") ) );
BOOST_CHECK( is_neg_nan( lexical_cast<test_t>("-nAn") ) );
BOOST_CHECK( is_neg_nan( lexical_cast<test_t>("-NaN") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("+Nan") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("+nAN") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("nan()") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("NAN(some string)") ) );
BOOST_CHECK_THROW( lexical_cast<test_t>("NAN(some string"), bad_lexical_cast );
BOOST_CHECK(lexical_cast<std::string>( (boost::math::changesign)(std::numeric_limits<test_t >::infinity()))
== "-inf" );
BOOST_CHECK(lexical_cast<std::string>( std::numeric_limits<test_t >::infinity()) == "inf" );
BOOST_CHECK(lexical_cast<std::string>( std::numeric_limits<test_t >::quiet_NaN()) == "nan" );
#if !defined(__ia64__) && !defined(_M_IA64)
BOOST_CHECK(lexical_cast<std::string>(
(boost::math::changesign)(std::numeric_limits<test_t >::quiet_NaN()))
== "-nan" );
#endif
#ifndef BOOST_LCAST_NO_WCHAR_T
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"inf") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"INF") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-inf") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-INF") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+inf") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+INF") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"infinity") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"INFINITY") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-infinity") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-INFINITY") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+infinity") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+INFINITY") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-infINIty") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-INFiniTY") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+inFINIty") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+INfinITY") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"nan") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"NAN") ) );
BOOST_CHECK( is_neg_nan( lexical_cast<test_t>(L"-nan") ) );
BOOST_CHECK( is_neg_nan( lexical_cast<test_t>(L"-NAN") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"+nan") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"+NAN") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"nan()") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"NAN(some string)") ) );
BOOST_CHECK_THROW( lexical_cast<test_t>(L"NAN(some string"), bad_lexical_cast );
BOOST_CHECK(lexical_cast<std::wstring>( (boost::math::changesign)(std::numeric_limits<test_t >::infinity()))
== L"-inf" );
BOOST_CHECK(lexical_cast<std::wstring>( std::numeric_limits<test_t >::infinity()) == L"inf" );
BOOST_CHECK(lexical_cast<std::wstring>( std::numeric_limits<test_t >::quiet_NaN()) == L"nan" );
#if !defined(__ia64__) && !defined(_M_IA64)
BOOST_CHECK(lexical_cast<std::wstring>(
(boost::math::changesign)(std::numeric_limits<test_t >::quiet_NaN()))
== L"-nan" );
#endif
#endif
}
void test_inf_nan_float()
{
test_inf_nan_templated<float >();
}
void test_inf_nan_double()
{
test_inf_nan_templated<double >();
}
void test_inf_nan_long_double()
{
test_inf_nan_templated<long double >();
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast inf anf nan parsing unit test");
suite->add(BOOST_TEST_CASE(&test_inf_nan_float));
suite->add(BOOST_TEST_CASE(&test_inf_nan_double));
suite->add(BOOST_TEST_CASE(&test_inf_nan_long_double));
return suite;
}
-217
View File
@@ -1,217 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2012.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/range/iterator_range.hpp>
using namespace boost;
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
#endif
struct class_with_user_defined_sream_operators {
int i;
operator int() const {
return i;
}
};
template <class CharT>
inline std::basic_istream<CharT>& operator >> (std::basic_istream<CharT>& istr, class_with_user_defined_sream_operators& rhs)
{
return istr >> rhs.i;
}
template <class RngT>
void do_test_iterator_range_impl(const RngT& rng)
{
BOOST_CHECK_EQUAL(lexical_cast<int>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<unsigned int>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<short>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<unsigned short>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<long int>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<unsigned long int>(rng), 1u);
#ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES
BOOST_CHECK_EQUAL(lexical_cast<float>(rng), 1.0f);
BOOST_CHECK_EQUAL(lexical_cast<double>(rng), 1.0);
BOOST_CHECK_EQUAL(lexical_cast<long double>(rng), 1.0L);
BOOST_CHECK_EQUAL(lexical_cast<class_with_user_defined_sream_operators>(rng), 1);
#endif
#if defined(BOOST_HAS_LONG_LONG)
BOOST_CHECK_EQUAL(lexical_cast<boost::ulong_long_type>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<boost::long_long_type>(rng), 1);
#elif defined(BOOST_HAS_MS_INT64)
BOOST_CHECK_EQUAL(lexical_cast<unsigned __int64>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<__int64>(rng), 1);
#endif
}
template <class CharT>
void test_it_range_using_any_chars(CharT* one, CharT* eleven)
{
typedef CharT test_char_type;
// Zero terminated
iterator_range<test_char_type*> rng1(one, one + 1);
do_test_iterator_range_impl(rng1);
iterator_range<const test_char_type*> crng1(one, one + 1);
do_test_iterator_range_impl(crng1);
// Non zero terminated
iterator_range<test_char_type*> rng2(eleven, eleven + 1);
do_test_iterator_range_impl(rng2);
iterator_range<const test_char_type*> crng2(eleven, eleven + 1);
do_test_iterator_range_impl(crng2);
}
template <class CharT>
void test_it_range_using_char(CharT* one, CharT* eleven)
{
typedef CharT test_char_type;
iterator_range<test_char_type*> rng1(one, one + 1);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(rng1), "1");
iterator_range<const test_char_type*> crng1(one, one + 1);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(crng1), "1");
iterator_range<test_char_type*> rng2(eleven, eleven + 1);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(rng2), "1");
iterator_range<const test_char_type*> crng2(eleven, eleven + 1);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(crng2), "1");
BOOST_CHECK_EQUAL(lexical_cast<float>(rng1), 1.0f);
BOOST_CHECK_EQUAL(lexical_cast<double>(rng1), 1.0);
BOOST_CHECK_EQUAL(lexical_cast<long double>(rng1), 1.0L);
BOOST_CHECK_EQUAL(lexical_cast<class_with_user_defined_sream_operators>(rng1), 1);
BOOST_CHECK_EQUAL(lexical_cast<float>(crng2), 1.0f);
BOOST_CHECK_EQUAL(lexical_cast<double>(crng2), 1.0);
BOOST_CHECK_EQUAL(lexical_cast<long double>(crng2), 1.0L);
BOOST_CHECK_EQUAL(lexical_cast<class_with_user_defined_sream_operators>(crng2), 1);
#ifndef BOOST_LCAST_NO_WCHAR_T
BOOST_CHECK(lexical_cast<std::wstring>(rng1) == L"1");
BOOST_CHECK(lexical_cast<std::wstring>(crng1) == L"1");
BOOST_CHECK(lexical_cast<std::wstring>(rng2) == L"1");
BOOST_CHECK(lexical_cast<std::wstring>(crng2) == L"1");
#endif
#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
typedef std::basic_string<char16_t> my_char16_string;
BOOST_CHECK(lexical_cast<my_char16_string>(rng1) == u"1");
BOOST_CHECK(lexical_cast<my_char16_string>(crng1) == u"1");
BOOST_CHECK(lexical_cast<my_char16_string>(rng2) == u"1");
BOOST_CHECK(lexical_cast<my_char16_string>(crng2) == u"1");
#endif
#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
typedef std::basic_string<char32_t> my_char32_string;
BOOST_CHECK(lexical_cast<my_char32_string>(rng1) == U"1");
BOOST_CHECK(lexical_cast<my_char32_string>(crng1) == U"1");
BOOST_CHECK(lexical_cast<my_char32_string>(rng2) == U"1");
BOOST_CHECK(lexical_cast<my_char32_string>(crng2) == U"1");
#endif
}
void test_char_iterator_ranges()
{
typedef char test_char_type;
test_char_type data1[] = "1";
test_char_type data2[] = "11";
test_it_range_using_any_chars(data1, data2);
test_it_range_using_char(data1, data2);
}
void test_unsigned_char_iterator_ranges()
{
typedef unsigned char test_char_type;
test_char_type data1[] = "1";
test_char_type data2[] = "11";
test_it_range_using_any_chars(data1, data2);
test_it_range_using_char(data1, data2);
}
void test_signed_char_iterator_ranges()
{
typedef signed char test_char_type;
test_char_type data1[] = "1";
test_char_type data2[] = "11";
test_it_range_using_any_chars(data1, data2);
test_it_range_using_char(data1, data2);
}
void test_wchar_iterator_ranges()
{
#ifndef BOOST_LCAST_NO_WCHAR_T
typedef wchar_t test_char_type;
test_char_type data1[] = L"1";
test_char_type data2[] = L"11";
test_it_range_using_any_chars(data1, data2);
#endif
BOOST_CHECK(true);
}
void test_char16_iterator_ranges()
{
#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS)
typedef char16_t test_char_type;
test_char_type data1[] = u"1";
test_char_type data2[] = u"11";
test_it_range_using_any_chars(data1, data2);
#endif
BOOST_CHECK(true);
}
void test_char32_iterator_ranges()
{
#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS)
typedef char32_t test_char_type;
test_char_type data1[] = U"1";
test_char_type data2[] = U"11";
test_it_range_using_any_chars(data1, data2);
#endif
BOOST_CHECK(true);
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast. Testing conversions using iterator_range<>");
suite->add(BOOST_TEST_CASE(&test_char_iterator_ranges));
suite->add(BOOST_TEST_CASE(&test_unsigned_char_iterator_ranges));
suite->add(BOOST_TEST_CASE(&test_signed_char_iterator_ranges));
suite->add(BOOST_TEST_CASE(&test_wchar_iterator_ranges));
suite->add(BOOST_TEST_CASE(&test_char16_iterator_ranges));
suite->add(BOOST_TEST_CASE(&test_char32_iterator_ranges));
return suite;
}
-92
View File
@@ -1,92 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Alexander Nasonov, 2006.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
//
// Test round-tripping conversion FPT -> string -> FPT,
// where FPT is Floating Point Type.
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
using namespace boost;
void test_round_conversion_float();
void test_round_conversion_double();
void test_round_conversion_long_double();
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast unit test");
suite->add(BOOST_TEST_CASE(&test_round_conversion_float));
suite->add(BOOST_TEST_CASE(&test_round_conversion_double));
suite->add(BOOST_TEST_CASE(&test_round_conversion_long_double));
return suite;
}
template<class T>
void test_round_conversion()
{
T epsilon = std::numeric_limits<T>::epsilon();
std::string const epsilon_s = boost::lexical_cast<std::string>(epsilon);
BOOST_CHECK(epsilon == lexical_cast<T>(epsilon_s));
T max_ = (std::numeric_limits<T>::max)();
std::string const max_s = boost::lexical_cast<std::string>(max_);
BOOST_CHECK(max_ == lexical_cast<T>(max_s));
T min_ = (std::numeric_limits<T>::min)();
std::string const min_s = boost::lexical_cast<std::string>(min_);
BOOST_CHECK(min_ == lexical_cast<T>(min_s));
T max_div137 = max_ / 137;
std::string max_div137_s = boost::lexical_cast<std::string>(max_div137);
BOOST_CHECK(max_div137 == lexical_cast<T>(max_div137_s));
T epsilon_mult137 = epsilon * 137;
std::string epsilon_mult137_s(lexical_cast<std::string>(epsilon_mult137));
BOOST_CHECK(epsilon_mult137 == lexical_cast<T>(epsilon_mult137_s));
}
// See bug http://tinyurl.com/vhpvo
template<class T>
void test_msvc_magic_values()
{
T magic_msvc = 0.00010000433948393407;
std::string magic_msvc_s = boost::lexical_cast<std::string>(magic_msvc);
BOOST_CHECK(magic_msvc == lexical_cast<T>(magic_msvc_s));
}
void test_round_conversion_float()
{
test_round_conversion<float>();
}
void test_round_conversion_double()
{
test_round_conversion<double>();
test_msvc_magic_values<double>();
}
void test_round_conversion_long_double()
{
test_round_conversion<long double>();
test_msvc_magic_values<long double>();
}
-95
View File
@@ -1,95 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2012.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/range/iterator_range.hpp>
#ifndef BOOST_NO_EXCEPTIONS
#error "This test must be compiled with -DBOOST_NO_EXCEPTIONS"
#endif
bool g_was_exception = false;
namespace boost {
void throw_exception(std::exception const & ) {
g_was_exception = true;
}
}
using namespace boost;
struct Escape
{
Escape(){}
Escape(const std::string& s)
: str_(s)
{}
std::string str_;
};
inline std::ostream& operator<< (std::ostream& o, const Escape& rhs)
{
return o << rhs.str_;
}
inline std::istream& operator>> (std::istream& i, Escape& rhs)
{
return i >> rhs.str_;
}
void test_exceptions_off()
{
Escape v("");
g_was_exception = false;
lexical_cast<char>(v);
BOOST_CHECK(g_was_exception);
g_was_exception = false;
lexical_cast<unsigned char>(v);
BOOST_CHECK(g_was_exception);
v = lexical_cast<Escape>(100);
BOOST_CHECK_EQUAL(lexical_cast<int>(v), 100);
BOOST_CHECK_EQUAL(lexical_cast<unsigned int>(v), 100u);
v = lexical_cast<Escape>(0.0);
BOOST_CHECK_EQUAL(lexical_cast<double>(v), 0.0);
BOOST_CHECK_EQUAL(lexical_cast<short>(100), 100);
BOOST_CHECK_EQUAL(lexical_cast<float>(0.0), 0.0);
g_was_exception = false;
lexical_cast<short>(700000);
BOOST_CHECK(g_was_exception);
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast. Testing with BOOST_NO_EXCEPTIONS");
suite->add(BOOST_TEST_CASE(&test_exceptions_off));
return suite;
}
-166
View File
@@ -1,166 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2012.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/range/iterator_range.hpp>
using namespace boost;
// Testing compilation and some basic usage with BOOST_NO_STD_LOCALE
// Tests are mainly copyied from lexical_cast_empty_input_test.cpp (something
// new added to test_empty_3)
#ifndef BOOST_NO_STD_LOCALE
#error "This test must be compiled with -DBOOST_NO_STD_LOCALE"
#endif
template <class T>
void do_test_on_empty_input(T& v)
{
BOOST_CHECK_THROW(lexical_cast<int>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<float>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<double>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<long double>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned int>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned short>(v), bad_lexical_cast);
#if defined(BOOST_HAS_LONG_LONG)
BOOST_CHECK_THROW(lexical_cast<boost::ulong_long_type>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<boost::long_long_type>(v), bad_lexical_cast);
#elif defined(BOOST_HAS_MS_INT64)
BOOST_CHECK_THROW(lexical_cast<unsigned __int64>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<__int64>(v), bad_lexical_cast);
#endif
}
void test_empty_1()
{
boost::iterator_range<char*> v;
do_test_on_empty_input(v);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(v), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
boost::iterator_range<const char*> cv;
do_test_on_empty_input(cv);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(cv), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(cv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(cv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(cv), bad_lexical_cast);
const boost::iterator_range<const char*> ccv;
do_test_on_empty_input(ccv);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(ccv), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(ccv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(ccv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(ccv), bad_lexical_cast);
}
void test_empty_2()
{
std::string v;
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
}
struct Escape
{
Escape(){}
Escape(const std::string& s)
: str_(s)
{}
std::string str_;
};
inline std::ostream& operator<< (std::ostream& o, const Escape& rhs)
{
return o << rhs.str_;
}
inline std::istream& operator>> (std::istream& i, Escape& rhs)
{
return i >> rhs.str_;
}
void test_empty_3()
{
Escape v("");
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
v = lexical_cast<Escape>(100);
BOOST_CHECK_EQUAL(lexical_cast<int>(v), 100);
BOOST_CHECK_EQUAL(lexical_cast<unsigned int>(v), 100u);
v = lexical_cast<Escape>(0.0);
BOOST_CHECK_EQUAL(lexical_cast<double>(v), 0.0);
}
namespace std {
inline std::ostream & operator<<(std::ostream & out, const std::vector<long> & v)
{
std::ostream_iterator<long> it(out);
std::copy(v.begin(), v.end(), it);
assert(out);
return out;
}
}
void test_empty_4()
{
std::vector<long> v;
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
}
struct my_string {
friend std::ostream &operator<<(std::ostream& sout, my_string const&/* st*/) {
return sout << "";
}
};
void test_empty_5()
{
my_string st;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(st), std::string());;
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast. Testing with BOOST_NO_STD_LOCALE");
suite->add(BOOST_TEST_CASE(&test_empty_1));
suite->add(BOOST_TEST_CASE(&test_empty_2));
suite->add(BOOST_TEST_CASE(&test_empty_3));
suite->add(BOOST_TEST_CASE(&test_empty_4));
suite->add(BOOST_TEST_CASE(&test_empty_5));
return suite;
}
-54
View File
@@ -1,54 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Alexander Nasonov, 2007.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
//
// Test that Source can be non-copyable.
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/noncopyable.hpp>
#include <boost/test/unit_test.hpp>
using namespace boost;
void test_noncopyable();
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast unit test");
suite->add(BOOST_TEST_CASE(&test_noncopyable));
return suite;
}
class Noncopyable : private boost::noncopyable
{
public:
Noncopyable() {}
};
inline std::ostream &operator<<(std::ostream &out, const Noncopyable&)
{
return out << "Noncopyable";
}
void test_noncopyable()
{
Noncopyable x;
BOOST_CHECK(boost::lexical_cast<std::string>(x) == "Noncopyable");
}
-96
View File
@@ -1,96 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2012.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
using namespace boost;
#if defined(BOOST_NO_STRINGSTREAM)
typedef std::strstream ss_t;
#else
typedef std::stringstream ss_t;
#endif
void test_void_pointers_conversions()
{
void *p_to_null = NULL;
const void *cp_to_data = "Some data";
char nonconst_data[5];
void *p_to_data = nonconst_data;
ss_t ss;
ss << p_to_null;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_null), ss.str());
ss.str(std::string());
ss << cp_to_data;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(cp_to_data), ss.str());
ss.str(std::string());
ss << p_to_data;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_data), ss.str());
ss.str(std::string());
}
struct incomplete_type;
void test_incomplete_type_pointers_conversions()
{
incomplete_type *p_to_null = NULL;
const incomplete_type *cp_to_data = NULL;
char nonconst_data[5];
incomplete_type *p_to_data = reinterpret_cast<incomplete_type*>(nonconst_data);
ss_t ss;
ss << p_to_null;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_null), ss.str());
ss.str(std::string());
ss << cp_to_data;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(cp_to_data), ss.str());
ss.str(std::string());
ss << p_to_data;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_data), ss.str());
ss.str(std::string());
}
struct ble;
typedef struct ble *meh;
std::ostream& operator <<(std::ostream &o, meh) {
o << "yay";
return o;
}
void test_inomplete_type_with_overloaded_ostream_op() {
meh heh = NULL;
ss_t ss;
ss << heh;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(heh), ss.str());
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast pinters test");
suite->add(BOOST_TEST_CASE(&test_void_pointers_conversions));
suite->add(BOOST_TEST_CASE(&test_incomplete_type_pointers_conversions));
suite->add(BOOST_TEST_CASE(&test_inomplete_type_with_overloaded_ostream_op));
return suite;
}
@@ -1,40 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void parseDate()
{
std::locale locale;
boost::date_time::format_date_parser<boost::gregorian::date, wchar_t> parser(L"", locale);
boost::date_time::special_values_parser<boost::gregorian::date, wchar_t> svp;
boost::gregorian::date date = parser.parse_date(L"", L"", svp);
(void)date;
}
int main()
{
#ifdef BOOST_MSVC
BOOST_STATIC_ASSERT((boost::is_same<wchar_t, unsigned short>::value));
#endif
parseDate();
return ::boost::lexical_cast<int>(L"1000") == 1000;
}
@@ -1,48 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
using namespace boost;
void test_typedefed_wchar_t_runtime()
{
#ifndef BOOST_LCAST_NO_WCHAR_T
#ifdef BOOST_MSVC
BOOST_STATIC_ASSERT((boost::is_same<wchar_t, unsigned short>::value));
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(L'A'), 65);
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(L'B'), 66);
BOOST_CHECK_EQUAL(boost::lexical_cast<wchar_t>(L"65"), 65);
BOOST_CHECK_EQUAL(boost::lexical_cast<wchar_t>(L"66"), 66);
#endif
#endif
BOOST_CHECK(1);
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast typedefed wchar_t runtime test");
suite->add(BOOST_TEST_CASE(&test_typedefed_wchar_t_runtime));
return suite;
}
-67
View File
@@ -1,67 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Alexander Nasonov, 2007.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
//
// This tests now must pass on vc8, because lexical_cast
// implementation has changed and it does not use stringstream for casts
// to integral types
#include <boost/config.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/cstdint.hpp>
#include <boost/test/unit_test.hpp>
#include <string>
using namespace boost;
// See also test_conversion_from_string_to_integral(CharT)
// in libs/conversion/lexical_cast_test.cpp
template<class T, class CharT>
void test_too_long_number(CharT zero)
{
typedef std::numeric_limits<T> limits;
std::basic_string<CharT> s;
std::basic_ostringstream<CharT> o;
o << (limits::max)() << zero;
s = o.str();
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
s[s.size()-1] += 9; // '0' -> '9'
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
if(limits::is_signed)
{
std::basic_ostringstream<CharT> o;
o << (limits::min)() << zero;
s = o.str();
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
s[s.size()-1] += 9; // '0' -> '9'
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
}
}
void test_vc8_bug()
{
test_too_long_number<boost::intmax_t>('0');
test_too_long_number<boost::uintmax_t>('0');
#if !defined(BOOST_LCAST_NO_WCHAR_T)
test_too_long_number<boost::intmax_t>(L'0');
test_too_long_number<boost::uintmax_t>(L'0');
#endif
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast vc8 bug unit test");
suite->add(BOOST_TEST_CASE(test_vc8_bug));
return suite;
}
-86
View File
@@ -1,86 +0,0 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011-2012.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
using namespace boost;
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
#endif
template <class CharT>
void test_impl(const CharT* wc_arr)
{
typedef CharT wide_char;
typedef std::basic_string<CharT> wide_string;
const char c_arr[] = "Test array of chars";
const unsigned char uc_arr[] = "Test array of chars";
const signed char sc_arr[] = "Test array of chars";
// Following tests depend on realization of std::locale
// and pass for popular compilers and STL realizations
BOOST_CHECK(boost::lexical_cast<wide_char>(c_arr[0]) == wc_arr[0]);
BOOST_CHECK(boost::lexical_cast<wide_string>(c_arr) == wide_string(wc_arr));
BOOST_CHECK(boost::lexical_cast<wide_string>(sc_arr) == wide_string(wc_arr) );
BOOST_CHECK(boost::lexical_cast<wide_string>(uc_arr) == wide_string(wc_arr) );
BOOST_CHECK_EQUAL(boost::lexical_cast<wide_char>(uc_arr[0]), wc_arr[0]);
BOOST_CHECK_EQUAL(boost::lexical_cast<wide_char>(sc_arr[0]), wc_arr[0]);
}
void test_char_types_conversions_wchar_t()
{
#ifndef BOOST_LCAST_NO_WCHAR_T
test_impl(L"Test array of chars");
#endif
BOOST_CHECK(true);
}
void test_char_types_conversions_char16_t()
{
#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
test_impl(u"Test array of chars");
#endif
BOOST_CHECK(true);
}
void test_char_types_conversions_char32_t()
{
#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
test_impl(U"Test array of chars");
#endif
BOOST_CHECK(true);
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast char => wide characters unit test (widening test)");
suite->add(BOOST_TEST_CASE(&test_char_types_conversions_wchar_t));
suite->add(BOOST_TEST_CASE(&test_char_types_conversions_char16_t));
suite->add(BOOST_TEST_CASE(&test_char_types_conversions_char32_t));
return suite;
}