mirror of
https://github.com/boostorg/conversion.git
synced 2026-08-04 04:24:11 +02:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a0a6c1942 | |||
| 49c0b2f333 | |||
| e9a5ac6d7a | |||
| ee3f643c5e | |||
| d44a6fcf8b | |||
| ac6e41d676 | |||
| 4224fa5deb | |||
| d6eea4ef81 |
@@ -120,10 +120,10 @@ void f( Fruit * fruit ) {
|
||||
<p><code>polymorphic_cast</code> was suggested by Bjarne Stroustrup in "The C++
|
||||
Programming Language".<br>
|
||||
<code>polymorphic_downcast</code> was contributed by <a href=
|
||||
"../../people/dave_abrahams.htm">Dave Abrahams</a>.<code><br>
|
||||
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>.<code><br>
|
||||
An old
|
||||
numeric_cast</code> that was contributed by <a href=
|
||||
"../../people/kevlin_henney.htm">Kevlin Henney</a> is now superseeded by the <a href="../numeric/conversion/doc/index.html">Boost Numeric Conversion Library</a></p>
|
||||
"http://www.boost.org/people/kevlin_henney.htm">Kevlin Henney</a> is now superseeded by the <a href="../numeric/conversion/doc/index.html">Boost Numeric Conversion Library</a></p>
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
// Copyright Alexander Nasonov & Paul A. Bristow 2006.
|
||||
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
|
||||
|
||||
#include <climits>
|
||||
#include <ios>
|
||||
#include <limits>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/integer_traits.hpp>
|
||||
|
||||
#ifndef BOOST_NO_IS_ABSTRACT
|
||||
// Fix for SF:1358600 - lexical_cast & pure virtual functions & VC 8 STL
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_abstract.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || \
|
||||
(defined(BOOST_MSVC) && (BOOST_MSVC<1310))
|
||||
|
||||
#define BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
||||
#include <boost/assert.hpp>
|
||||
#else
|
||||
#include <boost/static_assert.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace detail {
|
||||
|
||||
class lcast_abstract_stub {};
|
||||
|
||||
#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
||||
// Calculate an argument to pass to std::ios_base::precision from
|
||||
// lexical_cast. See alternative implementation for broken standard
|
||||
// libraries in lcast_get_precision below. Keep them in sync, please.
|
||||
template<class T>
|
||||
struct lcast_precision
|
||||
{
|
||||
#ifdef BOOST_NO_IS_ABSTRACT
|
||||
typedef std::numeric_limits<T> limits; // No fix for SF:1358600.
|
||||
#else
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
|
||||
boost::is_abstract<T>
|
||||
, std::numeric_limits<lcast_abstract_stub>
|
||||
, std::numeric_limits<T>
|
||||
>::type limits;
|
||||
#endif
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, use_default_precision =
|
||||
!limits::is_specialized || limits::is_exact
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized_bin =
|
||||
!use_default_precision &&
|
||||
limits::radix == 2 && limits::digits > 0
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized_dec =
|
||||
!use_default_precision &&
|
||||
limits::radix == 10 && limits::digits10 > 0
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(std::streamsize, streamsize_max =
|
||||
boost::integer_traits<std::streamsize>::const_max
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(unsigned int, precision_dec = limits::digits10 + 1U);
|
||||
|
||||
BOOST_STATIC_ASSERT(!is_specialized_dec ||
|
||||
precision_dec <= streamsize_max + 0UL
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(unsigned long, precision_bin =
|
||||
2UL + limits::digits * 30103UL / 100000UL
|
||||
);
|
||||
|
||||
BOOST_STATIC_ASSERT(!is_specialized_bin ||
|
||||
(limits::digits + 0UL < ULONG_MAX / 30103UL &&
|
||||
precision_bin > limits::digits10 + 0UL &&
|
||||
precision_bin <= streamsize_max + 0UL)
|
||||
);
|
||||
|
||||
BOOST_STATIC_CONSTANT(std::streamsize, value =
|
||||
is_specialized_bin ? precision_bin
|
||||
: is_specialized_dec ? precision_dec : 6
|
||||
);
|
||||
};
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline std::streamsize lcast_get_precision(T* = 0)
|
||||
{
|
||||
#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
|
||||
return lcast_precision<T>::value;
|
||||
#else // Follow lcast_precision algorithm at run-time:
|
||||
|
||||
#ifdef BOOST_NO_IS_ABSTRACT
|
||||
typedef std::numeric_limits<T> limits; // No fix for SF:1358600.
|
||||
#else
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
|
||||
boost::is_abstract<T>
|
||||
, std::numeric_limits<lcast_abstract_stub>
|
||||
, std::numeric_limits<T>
|
||||
>::type limits;
|
||||
#endif
|
||||
|
||||
bool const use_default_precision =
|
||||
!limits::is_specialized || limits::is_exact;
|
||||
|
||||
if(!use_default_precision)
|
||||
{ // Includes all built-in floating-point types, float, double ...
|
||||
// and UDT types for which digits (significand bits) is defined (not zero)
|
||||
|
||||
bool const is_specialized_bin =
|
||||
limits::radix == 2 && limits::digits > 0;
|
||||
bool const is_specialized_dec =
|
||||
limits::radix == 10 && limits::digits10 > 0;
|
||||
std::streamsize const streamsize_max =
|
||||
(boost::integer_traits<std::streamsize>::max)();
|
||||
|
||||
if(is_specialized_bin)
|
||||
{ // Floating-point types with
|
||||
// limits::digits defined by the specialization.
|
||||
|
||||
unsigned long const digits = limits::digits;
|
||||
unsigned long const precision = 2UL + digits * 30103UL / 100000UL;
|
||||
// unsigned long is selected because it is at least 32-bits
|
||||
// and thus ULONG_MAX / 30103UL is big enough for all types.
|
||||
BOOST_ASSERT(
|
||||
digits < ULONG_MAX / 30103UL &&
|
||||
precision > limits::digits10 + 0UL &&
|
||||
precision <= streamsize_max + 0UL
|
||||
);
|
||||
return precision;
|
||||
}
|
||||
else if(is_specialized_dec)
|
||||
{ // Decimal Floating-point type, most likely a User Defined Type
|
||||
// rather than a real floating-point hardware type.
|
||||
unsigned int const precision = limits::digits10 + 1U;
|
||||
BOOST_ASSERT(precision <= streamsize_max + 0UL);
|
||||
return precision;
|
||||
}
|
||||
}
|
||||
|
||||
// Integral type (for which precision has no effect)
|
||||
// or type T for which limits is NOT specialized,
|
||||
// so assume stream precision remains the default 6 decimal digits.
|
||||
// Warning: if your User-defined Floating-point type T is NOT specialized,
|
||||
// then you may lose accuracy by only using 6 decimal digits.
|
||||
// To avoid this, you need to specialize T with either
|
||||
// radix == 2 and digits == the number of significand bits,
|
||||
// OR
|
||||
// radix = 10 and digits10 == the number of decimal digits.
|
||||
|
||||
return 6;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void lcast_set_precision(std::ios_base& stream, T*)
|
||||
{
|
||||
stream.precision(lcast_get_precision<T>());
|
||||
}
|
||||
|
||||
template<class Source, class Target>
|
||||
inline void lcast_set_precision(std::ios_base& stream, Source*, Target*)
|
||||
{
|
||||
std::streamsize const s = lcast_get_precision((Source*)0);
|
||||
std::streamsize const t = lcast_get_precision((Target*)0);
|
||||
stream.precision(s > t ? s : t);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
|
||||
|
||||
Executable → Regular
+1
-1
@@ -23,7 +23,7 @@ inline T implicit_cast (typename mpl::identity<T>::type x) {
|
||||
//template <typename T>
|
||||
//void implicit_cast (...);
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // IMPLICIT_CAST_DWA200356_HPP
|
||||
|
||||
+984
-31
File diff suppressed because it is too large
Load Diff
+38
-2
@@ -20,6 +20,10 @@
|
||||
<a href="#lexical_cast"><code>lexical_cast</code></a></li>
|
||||
<li>
|
||||
<a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a></li>
|
||||
<li>
|
||||
<a href="#faq">Frequently Asked Questions</a></li>
|
||||
<li>
|
||||
<a href="#references">References</a></li>
|
||||
<li>
|
||||
<a href="#changes">Changes</a></li>
|
||||
</ul>
|
||||
@@ -160,7 +164,7 @@ void log_errno(int yoko)
|
||||
and an instance of the result type on the right.
|
||||
</li>
|
||||
<li>
|
||||
Both <code>Source</code> and <code>Target</code> are <i>CopyConstructible</i> [20.1.3].
|
||||
<code>Target</code> is <i>CopyConstructible</i> [20.1.3].
|
||||
</li>
|
||||
<li>
|
||||
<code>Target</code> is <i>DefaultConstructible</i>, meaning that it is possible
|
||||
@@ -192,7 +196,39 @@ public:
|
||||
failure.
|
||||
<hr>
|
||||
|
||||
<h2><a name="faq">Frequently Asked Questions</h2>
|
||||
<p> Q: Why does <code>lexical_cast<int8_t>("127")</code> throw <code>bad_lexical_cast</code>?
|
||||
<br> A: The type <code>int8_t</code> is a typedef to <code>char</code> or <code>signed char</code>.
|
||||
Lexical conversion to these types is simply reading a byte from source but since the source has
|
||||
more than one byte, the exception is thrown.
|
||||
<p>Please use other integer types such as <code>int</code> or <code>short int</code>. If bounds checking
|
||||
is important, you can also call <a href="../../libs/numeric/conversion/doc/numeric_cast.html">numeric_cast</a>:
|
||||
|
||||
<pre><a href="../../libs/numeric/conversion/doc/numeric_cast.html">numeric_cast</a><int8_t>(lexical_cast<int>("127"));</pre>
|
||||
|
||||
<p> Q: What does <code>lexical_cast<std::string></code> of an <code>int8_t</code> or <code>uint8_t</code> not do what I expect?
|
||||
<br> A: As above, note that <code>int8_t</code> and <code>uint8_t</code> are actually chars and are formatted as such. To avoid this, cast to an integer type first:
|
||||
|
||||
<pre>lexical_cast<std::string>(static_cast<int>(n));</pre>
|
||||
|
||||
<p> Q: The implementation always resets the <code>ios_base::skipws</code> flag of an underlying stream object. It breaks my <code>operator>></code> that works only in presence of this flag. Can you remove code that resets the flag?
|
||||
<br> A: May be in a future version. There is no requirement in <a href="#n1973">[N1973]</a> to reset the flag but remember that <a href="#n1973">[N1973]</a> is not yet accepted by the committee. By the way, it's a great opportunity to make your <code>operator>></code> conform to the standard. Read a good C++ book, study <code>std::sentry</code> and <a href="../../libs/io/doc/ios_state.html">ios_state_saver</a>.
|
||||
</ul>
|
||||
<h2><a name="references">References</h2>
|
||||
<ul type="square">
|
||||
<a name="n1973"></a><li> [N1973] Kevlin Henney, Beman Dawes, Lexical Conversion Library Proposal for TR2,
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1973.html">N1973</a>.
|
||||
<a name="tuning"></a><li> [Tuning] Alexander Nasonov, Fine Tuning for lexical_cast,
|
||||
<a href="http://www.accu.org/var/uploads/journals/overload74.pdf">Overload #74</a>,
|
||||
August 2006.</li>
|
||||
</ul>
|
||||
<h2><a name="changes">Changes</a></h2>
|
||||
<h3>August, October 2006:</h3>
|
||||
<ul type="square">
|
||||
<li>Better performance for many combinations of <code>Source</code> and <code>Target</code>
|
||||
types. Refer to <a href="#tuning">[Tuning]</a> for more details.
|
||||
</li>
|
||||
</ul>
|
||||
<h3>June 2005:</h3>
|
||||
<ul type="square">
|
||||
<li>Call-by-const reference for the parameters. This requires partial specialization
|
||||
@@ -231,4 +267,4 @@ public:
|
||||
|
||||
<div align="right"><small><i>© Copyright Kevlin Henney, 2000–2005</i></small></div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
+432
-1
@@ -3,6 +3,7 @@
|
||||
// See http://www.boost.org for most recent version, including documentation.
|
||||
//
|
||||
// Copyright Terje Slettebø and Kevlin Henney, 2005.
|
||||
// Copyright Alexander Nasonov, 2006.
|
||||
//
|
||||
// Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
@@ -23,12 +24,37 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/floating_point_comparison.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#if defined(BOOST_NO_STRINGSTREAM) || \
|
||||
defined(BOOST_NO_STD_WSTRING) || \
|
||||
defined(BOOST_NO_STD_LOCALE)
|
||||
#define DISABLE_WIDE_CHAR_SUPPORT
|
||||
#endif
|
||||
|
||||
#if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) \
|
||||
&& !(defined(BOOST_MSVC) && BOOST_MSVC < 1300)
|
||||
#define LCAST_TEST_LONGLONG
|
||||
#endif
|
||||
|
||||
template<class CharT>
|
||||
struct my_traits : std::char_traits<CharT>
|
||||
{
|
||||
};
|
||||
|
||||
template<class CharT>
|
||||
struct my_allocator : std::allocator<CharT>
|
||||
{
|
||||
};
|
||||
|
||||
// Test all 65536 values if true:
|
||||
bool const lcast_test_small_integral_types_completely = false;
|
||||
|
||||
// lcast_integral_test_counter: use when testing all values of an integral
|
||||
// types is not possible. Max. portable value is 32767.
|
||||
int const lcast_integral_test_counter=1000;
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void test_conversion_to_char();
|
||||
@@ -44,6 +70,22 @@ void test_conversion_from_wstring();
|
||||
void test_conversion_to_wstring();
|
||||
void test_bad_lexical_cast();
|
||||
void test_no_whitespace_stripping();
|
||||
void test_conversion_from_to_short();
|
||||
void test_conversion_from_to_ushort();
|
||||
void test_conversion_from_to_int();
|
||||
void test_conversion_from_to_uint();
|
||||
void test_conversion_from_to_long();
|
||||
void test_conversion_from_to_ulong();
|
||||
#ifdef LCAST_TEST_LONGLONG
|
||||
void test_conversion_from_to_longlong();
|
||||
void test_conversion_from_to_ulonglong();
|
||||
#endif
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
void test_traits();
|
||||
void test_wtraits();
|
||||
void test_allocator();
|
||||
void test_wallocator();
|
||||
#endif
|
||||
|
||||
unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||
{
|
||||
@@ -64,6 +106,23 @@ unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||
#endif
|
||||
suite->add(BOOST_TEST_CASE(test_bad_lexical_cast));
|
||||
suite->add(BOOST_TEST_CASE(test_no_whitespace_stripping));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_short));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ushort));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_int));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uint));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long));
|
||||
#ifdef LCAST_TEST_LONGLONG
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_longlong));
|
||||
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong));
|
||||
#endif
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
suite->add(BOOST_TEST_CASE(&test_traits));
|
||||
suite->add(BOOST_TEST_CASE(&test_wtraits));
|
||||
suite->add(BOOST_TEST_CASE(&test_allocator));
|
||||
suite->add(BOOST_TEST_CASE(&test_wallocator));
|
||||
#endif
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
@@ -95,10 +154,15 @@ void test_conversion_to_int()
|
||||
BOOST_CHECK_EQUAL(0, lexical_cast<int>('0'));
|
||||
BOOST_CHECK_THROW(lexical_cast<int>('A'), bad_lexical_cast);
|
||||
BOOST_CHECK_EQUAL(1, lexical_cast<int>(1));
|
||||
BOOST_CHECK_EQUAL(1, lexical_cast<int>(1.0));
|
||||
|
||||
BOOST_CHECK_EQUAL(
|
||||
(std::numeric_limits<int>::max)(),
|
||||
lexical_cast<int>((std::numeric_limits<int>::max)()));
|
||||
BOOST_CHECK_EQUAL(1, lexical_cast<int>(1.0));
|
||||
|
||||
BOOST_CHECK_EQUAL(
|
||||
(std::numeric_limits<int>::min)(),
|
||||
lexical_cast<int>((std::numeric_limits<int>::min)()));
|
||||
|
||||
BOOST_CHECK_THROW(lexical_cast<int>(1.23), bad_lexical_cast);
|
||||
|
||||
@@ -167,6 +231,9 @@ void test_conversion_to_bool()
|
||||
|
||||
void test_conversion_to_string()
|
||||
{
|
||||
char buf[] = "hello";
|
||||
char* str = buf;
|
||||
BOOST_CHECK_EQUAL(str, lexical_cast<std::string>(str));
|
||||
BOOST_CHECK_EQUAL("A", lexical_cast<std::string>('A'));
|
||||
BOOST_CHECK_EQUAL(" ", lexical_cast<std::string>(' '));
|
||||
BOOST_CHECK_EQUAL("123", lexical_cast<std::string>(123));
|
||||
@@ -239,6 +306,8 @@ void test_conversion_to_wchar_t()
|
||||
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>(1));
|
||||
BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>(0));
|
||||
BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>('1'));
|
||||
BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>('0'));
|
||||
BOOST_CHECK_THROW(lexical_cast<wchar_t>(123), bad_lexical_cast);
|
||||
BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>(1.0));
|
||||
BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>(0.0));
|
||||
@@ -280,6 +349,9 @@ void test_conversion_from_wstring()
|
||||
void test_conversion_to_wstring()
|
||||
{
|
||||
#ifndef DISABLE_WIDE_CHAR_SUPPORT
|
||||
wchar_t buf[] = L"hello";
|
||||
wchar_t* str = buf;
|
||||
BOOST_CHECK(str == lexical_cast<std::wstring>(str));
|
||||
BOOST_CHECK(L"123" == lexical_cast<std::wstring>(123));
|
||||
BOOST_CHECK(L"1.23" == lexical_cast<std::wstring>(1.23));
|
||||
BOOST_CHECK(L"1.111111111" == lexical_cast<std::wstring>(1.111111111));
|
||||
@@ -288,6 +360,7 @@ void test_conversion_to_wstring()
|
||||
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
BOOST_CHECK(L"A" == lexical_cast<std::wstring>(L'A'));
|
||||
BOOST_CHECK(L" " == lexical_cast<std::wstring>(L' '));
|
||||
BOOST_CHECK(L"A" == lexical_cast<std::wstring>('A'));
|
||||
#endif
|
||||
BOOST_CHECK(L"Test" == lexical_cast<std::wstring>(L"Test"));
|
||||
BOOST_CHECK(L" " == lexical_cast<std::wstring>(L" "));
|
||||
@@ -318,3 +391,361 @@ void test_no_whitespace_stripping()
|
||||
BOOST_CHECK_THROW(lexical_cast<int>(" 123"), bad_lexical_cast);
|
||||
BOOST_CHECK_THROW(lexical_cast<int>("123 "), bad_lexical_cast);
|
||||
}
|
||||
|
||||
// Replace "-,999" with "-999".
|
||||
template<class CharT>
|
||||
std::basic_string<CharT> to_str_gcc_workaround(std::basic_string<CharT> str)
|
||||
{
|
||||
std::locale loc;
|
||||
std::numpunct<CharT> const& np = BOOST_USE_FACET(std::numpunct<CharT>, loc);
|
||||
std::ctype<CharT> const& ct = BOOST_USE_FACET(std::ctype<CharT>, loc);
|
||||
|
||||
if(np.grouping().empty())
|
||||
return str;
|
||||
|
||||
CharT prefix[3] = { ct.widen('-'), np.thousands_sep(), CharT() };
|
||||
|
||||
if(str.find(prefix) != 0)
|
||||
return str;
|
||||
|
||||
prefix[1] = CharT();
|
||||
str.replace(0, 2, prefix);
|
||||
return str;
|
||||
}
|
||||
|
||||
template<class CharT, class T>
|
||||
std::basic_string<CharT> to_str(T t)
|
||||
{
|
||||
std::basic_ostringstream<CharT> o;
|
||||
o << t;
|
||||
return to_str_gcc_workaround(o.str());
|
||||
}
|
||||
|
||||
template<class T, class CharT>
|
||||
void test_conversion_from_integral_to_char(CharT zero)
|
||||
{
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(0)) == zero + 0);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(1)) == zero + 1);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(2)) == zero + 2);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(3)) == zero + 3);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(4)) == zero + 4);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(5)) == zero + 5);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(6)) == zero + 6);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(7)) == zero + 7);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(8)) == zero + 8);
|
||||
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(9)) == zero + 9);
|
||||
|
||||
BOOST_CHECK_THROW(lexical_cast<CharT>(static_cast<T>(10)), bad_lexical_cast);
|
||||
|
||||
T t = (std::numeric_limits<T>::max)();
|
||||
BOOST_CHECK_THROW(lexical_cast<CharT>(t), bad_lexical_cast);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_conversion_from_integral_to_integral()
|
||||
{
|
||||
T t = 0;
|
||||
BOOST_CHECK(lexical_cast<T>(t) == t);
|
||||
|
||||
// Next two variables are used to supress warnings.
|
||||
int st = 32767; unsigned int ut = st;
|
||||
t = st;
|
||||
BOOST_CHECK(lexical_cast<short>(t) == st);
|
||||
BOOST_CHECK(lexical_cast<unsigned short>(t) == ut);
|
||||
BOOST_CHECK(lexical_cast<int>(t) == st);
|
||||
BOOST_CHECK(lexical_cast<unsigned int>(t) == ut);
|
||||
BOOST_CHECK(lexical_cast<long>(t) == st);
|
||||
BOOST_CHECK(lexical_cast<unsigned long>(t) == ut);
|
||||
|
||||
t = (std::numeric_limits<T>::max)();
|
||||
BOOST_CHECK(lexical_cast<T>(t) == t);
|
||||
|
||||
t = (std::numeric_limits<T>::min)();
|
||||
BOOST_CHECK(lexical_cast<T>(t) == t);
|
||||
}
|
||||
|
||||
template<class T, class CharT>
|
||||
void test_conversion_from_integral_to_string(CharT)
|
||||
{
|
||||
typedef std::numeric_limits<T> limits;
|
||||
typedef std::basic_string<CharT> string_type;
|
||||
|
||||
T t;
|
||||
|
||||
t = (limits::min)();
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
|
||||
t = (limits::max)();
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
|
||||
if(limits::digits <= 16 && lcast_test_small_integral_types_completely)
|
||||
// min and max have already been tested.
|
||||
for(t = 1 + (limits::min)(); t != (limits::max)(); ++t)
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
else
|
||||
{
|
||||
T const min_val = (limits::min)();
|
||||
T const max_val = (limits::max)();
|
||||
T const half_max_val = max_val / 2;
|
||||
T const cnt = lcast_integral_test_counter; // to supress warnings
|
||||
unsigned int const counter = cnt < half_max_val ? cnt : half_max_val;
|
||||
|
||||
unsigned int i;
|
||||
|
||||
// Test values around min:
|
||||
t = min_val;
|
||||
for(i = 0; i < counter; ++i, ++t)
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
|
||||
// Test values around max:
|
||||
t = max_val;
|
||||
for(i = 0; i < counter; ++i, --t)
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
|
||||
// Test values around zero:
|
||||
if(limits::is_signed)
|
||||
for(t = -counter; t < static_cast<T>(counter); ++t)
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
|
||||
// Test values around 100, 1000, 10000, ...
|
||||
T ten_power = 100;
|
||||
for(int e = 2; e <= limits::digits10; ++e, ten_power *= 10)
|
||||
{
|
||||
// ten_power + 100 probably never overflows
|
||||
for(t = ten_power - 100; t != ten_power + 100; ++t)
|
||||
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, class CharT>
|
||||
void test_conversion_from_string_to_integral(CharT)
|
||||
{
|
||||
typedef std::numeric_limits<T> limits;
|
||||
|
||||
T t;
|
||||
|
||||
t = (limits::min)();
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
|
||||
t = (limits::max)();
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
|
||||
if(limits::digits <= 16 && lcast_test_small_integral_types_completely)
|
||||
// min and max have already been tested.
|
||||
for(t = 1 + (limits::min)(); t != (limits::max)(); ++t)
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
else
|
||||
{
|
||||
T const min_val = (limits::min)();
|
||||
T const max_val = (limits::max)();
|
||||
T const half_max_val = max_val / 2;
|
||||
T const cnt = lcast_integral_test_counter; // to supress warnings
|
||||
unsigned int const counter = cnt < half_max_val ? cnt : half_max_val;
|
||||
|
||||
unsigned int i;
|
||||
|
||||
// Test values around min:
|
||||
t = min_val;
|
||||
for(i = 0; i < counter; ++i, ++t)
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
|
||||
// Test values around max:
|
||||
t = max_val;
|
||||
for(i = 0; i < counter; ++i, --t)
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
|
||||
// Test values around zero:
|
||||
if(limits::is_signed)
|
||||
for(t = -counter; t < static_cast<T>(counter); ++t)
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
|
||||
// Test values around 100, 1000, 10000, ...
|
||||
T ten_power = 100;
|
||||
for(int e = 2; e <= limits::digits10; ++e, ten_power *= 10)
|
||||
{
|
||||
// ten_power + 100 probably never overflows
|
||||
for(t = ten_power - 100; t != ten_power + 100; ++t)
|
||||
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_conversion_from_to_integral_for_locale()
|
||||
{
|
||||
test_conversion_from_integral_to_integral<T>();
|
||||
test_conversion_from_integral_to_string<T>('0');
|
||||
test_conversion_from_string_to_integral<T>('0');
|
||||
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
test_conversion_from_integral_to_string<T>(L'0');
|
||||
test_conversion_from_string_to_integral<T>(L'0');
|
||||
#endif
|
||||
}
|
||||
|
||||
struct restore_oldloc
|
||||
{
|
||||
std::locale oldloc;
|
||||
~restore_oldloc() { std::locale::global(oldloc); }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
void test_conversion_from_to_integral()
|
||||
{
|
||||
char const zero = '0';
|
||||
signed char const szero = '0';
|
||||
unsigned char const uzero = '0';
|
||||
test_conversion_from_integral_to_char<T>(zero);
|
||||
test_conversion_from_integral_to_char<T>(szero);
|
||||
test_conversion_from_integral_to_char<T>(uzero);
|
||||
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
|
||||
wchar_t const wzero = L'0';
|
||||
test_conversion_from_integral_to_char<T>(wzero);
|
||||
#endif
|
||||
|
||||
// test_conversion_from_to_integral_for_locale
|
||||
|
||||
typedef std::numpunct<char> numpunct;
|
||||
|
||||
restore_oldloc guard;
|
||||
std::locale const& oldloc = guard.oldloc;
|
||||
|
||||
std::string grouping1 = BOOST_USE_FACET(numpunct, oldloc).grouping();
|
||||
std::string grouping2(grouping1);
|
||||
|
||||
test_conversion_from_to_integral_for_locale<T>();
|
||||
|
||||
try
|
||||
{
|
||||
std::locale newloc("");
|
||||
std::locale::global(newloc);
|
||||
|
||||
grouping2 = BOOST_USE_FACET(numpunct, newloc).grouping();
|
||||
}
|
||||
catch(std::exception const& ex)
|
||||
{
|
||||
std::string msg("Failed to set system locale: ");
|
||||
msg += ex.what();
|
||||
BOOST_TEST_MESSAGE(msg);
|
||||
}
|
||||
|
||||
if(grouping1 != grouping2)
|
||||
test_conversion_from_to_integral_for_locale<T>();
|
||||
|
||||
if(grouping1.empty() && grouping2.empty())
|
||||
BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested");
|
||||
}
|
||||
|
||||
void test_conversion_from_to_short()
|
||||
{
|
||||
test_conversion_from_to_integral<short>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_ushort()
|
||||
{
|
||||
test_conversion_from_to_integral<unsigned short>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_int()
|
||||
{
|
||||
test_conversion_from_to_integral<int>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_uint()
|
||||
{
|
||||
test_conversion_from_to_integral<unsigned int>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_ulong()
|
||||
{
|
||||
test_conversion_from_to_integral<unsigned long>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_long()
|
||||
{
|
||||
test_conversion_from_to_integral<long>();
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_LONG_LONG)
|
||||
|
||||
void test_conversion_from_to_longlong()
|
||||
{
|
||||
test_conversion_from_to_integral<boost::long_long_type>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_ulonglong()
|
||||
{
|
||||
test_conversion_from_to_integral<boost::ulong_long_type>();
|
||||
}
|
||||
|
||||
#elif defined(LCAST_TEST_LONGLONG)
|
||||
|
||||
void test_conversion_from_to_longlong()
|
||||
{
|
||||
test_conversion_from_to_integral<__int64>();
|
||||
}
|
||||
|
||||
void test_conversion_from_to_ulonglong()
|
||||
{
|
||||
test_conversion_from_to_integral<unsigned __int64>();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
void test_traits()
|
||||
{
|
||||
typedef std::basic_string<char, my_traits<char> > my_string;
|
||||
|
||||
my_string const s("s");
|
||||
BOOST_CHECK(boost::lexical_cast<char>(s) == s[0]);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(s) == s);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(-1) == "-1");
|
||||
}
|
||||
|
||||
void test_wtraits()
|
||||
{
|
||||
typedef std::basic_string<wchar_t, my_traits<wchar_t> > my_string;
|
||||
|
||||
my_string const s(L"s");
|
||||
BOOST_CHECK(boost::lexical_cast<wchar_t>(s) == s[0]);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(s) == s);
|
||||
//BOOST_CHECK(boost::lexical_cast<my_string>(-1) == L"-1");
|
||||
// Commented out because gcc 3.3 doesn't support this:
|
||||
// basic_ostream<wchar_t, my_traits<wchar_t> > o; o << -1;
|
||||
}
|
||||
|
||||
void test_allocator()
|
||||
{
|
||||
typedef std::basic_string< char
|
||||
, std::char_traits<char>
|
||||
, my_allocator<char>
|
||||
> my_string;
|
||||
|
||||
my_string s("s");
|
||||
BOOST_CHECK(boost::lexical_cast<char>(s) == s[0]);
|
||||
BOOST_CHECK(boost::lexical_cast<std::string>(s) == "s");
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(s) == s);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(1) == "1");
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>("s") == s);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(std::string("s")) == s);
|
||||
}
|
||||
|
||||
void test_wallocator()
|
||||
{
|
||||
typedef std::basic_string< wchar_t
|
||||
, std::char_traits<wchar_t>
|
||||
, my_allocator<wchar_t>
|
||||
> my_string;
|
||||
|
||||
my_string s(L"s");
|
||||
BOOST_CHECK(boost::lexical_cast<wchar_t>(s) == s[0]);
|
||||
BOOST_CHECK(boost::lexical_cast<std::wstring>(s) == L"s");
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(s) == s);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(1) == L"1");
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(L"s") == s);
|
||||
BOOST_CHECK(boost::lexical_cast<my_string>(std::wstring(L"s")) == s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@ test-suite conversion
|
||||
[ run ../cast_test.cpp ]
|
||||
[ run ../numeric_cast_test.cpp ]
|
||||
[ run ../lexical_cast_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
[ run lexical_cast_loopback_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
[ run lexical_cast_abstract_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
[ run lexical_cast_noncopyable_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// Unit test for boost::lexical_cast.
|
||||
//
|
||||
// See http://www.boost.org for most recent version, including documentation.
|
||||
//
|
||||
// Copyright Sergey Shandar 2005, Alexander Nasonov, 2007.
|
||||
//
|
||||
// Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
|
||||
//
|
||||
// Test abstract class. Bug 1358600:
|
||||
// http://sf.net/tracker/?func=detail&aid=1358600&group_id=7586&atid=107586
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#pragma warning(disable: 193 383 488 981 1418 1419)
|
||||
#elif defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
|
||||
#endif
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void test_abstract();
|
||||
|
||||
unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||
{
|
||||
unit_test_framework::test_suite *suite =
|
||||
BOOST_TEST_SUITE("lexical_cast unit test");
|
||||
suite->add(BOOST_TEST_CASE(&test_abstract));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
virtual void out(std::ostream &) const = 0;
|
||||
};
|
||||
|
||||
class B: public A
|
||||
{
|
||||
public:
|
||||
virtual void out(std::ostream &O) const { O << "B"; }
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &O, const A &a)
|
||||
{
|
||||
a.out(O);
|
||||
return O;
|
||||
};
|
||||
|
||||
void test_abstract()
|
||||
{
|
||||
const A &a = B();
|
||||
BOOST_CHECK(boost::lexical_cast<std::string>(a) == "B");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
// Unit test for boost::lexical_cast.
|
||||
//
|
||||
// See http://www.boost.org for most recent version, including documentation.
|
||||
//
|
||||
// Copyright Alexander Nasonov, 2006.
|
||||
//
|
||||
// Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
|
||||
//
|
||||
// Test round-tripping conversion FPT -> string -> FPT,
|
||||
// where FPT is Floating Point Type.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#pragma warning(disable: 193 383 488 981 1418 1419)
|
||||
#elif defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
|
||||
#endif
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void test_round_conversion_float();
|
||||
void test_round_conversion_double();
|
||||
void test_round_conversion_long_double();
|
||||
|
||||
unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||
{
|
||||
unit_test_framework::test_suite *suite =
|
||||
BOOST_TEST_SUITE("lexical_cast unit test");
|
||||
suite->add(BOOST_TEST_CASE(&test_round_conversion_float));
|
||||
suite->add(BOOST_TEST_CASE(&test_round_conversion_double));
|
||||
suite->add(BOOST_TEST_CASE(&test_round_conversion_long_double));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_round_conversion()
|
||||
{
|
||||
T epsilon = std::numeric_limits<T>::epsilon();
|
||||
std::string const epsilon_s = boost::lexical_cast<std::string>(epsilon);
|
||||
BOOST_CHECK(epsilon == lexical_cast<T>(epsilon_s));
|
||||
|
||||
T max_ = (std::numeric_limits<T>::max)();
|
||||
std::string const max_s = boost::lexical_cast<std::string>(max_);
|
||||
BOOST_CHECK(max_ == lexical_cast<T>(max_s));
|
||||
|
||||
T min_ = (std::numeric_limits<T>::min)();
|
||||
std::string const min_s = boost::lexical_cast<std::string>(min_);
|
||||
BOOST_CHECK(min_ == lexical_cast<T>(min_s));
|
||||
|
||||
T max_div137 = max_ / 137;
|
||||
std::string max_div137_s = boost::lexical_cast<std::string>(max_div137);
|
||||
BOOST_CHECK(max_div137 == lexical_cast<T>(max_div137_s));
|
||||
|
||||
T epsilon_mult137 = epsilon * 137;
|
||||
std::string epsilon_mult137_s(lexical_cast<std::string>(epsilon_mult137));
|
||||
BOOST_CHECK(epsilon_mult137 == lexical_cast<T>(epsilon_mult137_s));
|
||||
|
||||
}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
// See bug http://tinyurl.com/vhpvo
|
||||
template<class T>
|
||||
void test_msvc_magic_values()
|
||||
{
|
||||
T magic_msvc = 0.00010000433948393407;
|
||||
std::string magic_msvc_s = boost::lexical_cast<std::string>(magic_msvc);
|
||||
BOOST_CHECK(magic_msvc == lexical_cast<T>(magic_msvc_s));
|
||||
}
|
||||
#endif
|
||||
|
||||
void test_round_conversion_float()
|
||||
{
|
||||
test_round_conversion<float>();
|
||||
}
|
||||
|
||||
void test_round_conversion_double()
|
||||
{
|
||||
test_round_conversion<double>();
|
||||
#if defined(BOOST_MSVC)
|
||||
test_msvc_magic_values<double>();
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_round_conversion_long_double()
|
||||
{
|
||||
test_round_conversion<long double>();
|
||||
#if defined(BOOST_MSVC)
|
||||
test_msvc_magic_values<long double>();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// Unit test for boost::lexical_cast.
|
||||
//
|
||||
// See http://www.boost.org for most recent version, including documentation.
|
||||
//
|
||||
// Copyright Alexander Nasonov, 2007.
|
||||
//
|
||||
// Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
|
||||
//
|
||||
// Test that Source can be non-copyable.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#pragma warning(disable: 193 383 488 981 1418 1419)
|
||||
#elif defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
|
||||
#endif
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void test_noncopyable();
|
||||
|
||||
unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||
{
|
||||
unit_test_framework::test_suite *suite =
|
||||
BOOST_TEST_SUITE("lexical_cast unit test");
|
||||
suite->add(BOOST_TEST_CASE(&test_noncopyable));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
class Noncopyable : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
Noncopyable() {}
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &out, const Noncopyable&)
|
||||
{
|
||||
return out << "Noncopyable";
|
||||
}
|
||||
|
||||
void test_noncopyable()
|
||||
{
|
||||
Noncopyable x;
|
||||
BOOST_CHECK(boost::lexical_cast<std::string>(x) == "Noncopyable");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user