diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 12a89f8..4f68452 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -86,6 +86,14 @@ namespace boost typedef char type; }; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct stream_char< std::basic_string > + { + typedef CharT type; + }; +#endif + #ifndef DISABLE_WIDE_CHAR_SUPPORT #ifndef BOOST_NO_INTRINSIC_WCHAR_T template<> @@ -107,11 +115,13 @@ namespace boost typedef wchar_t type; }; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template<> struct stream_char { typedef wchar_t type; }; +#endif #endif template @@ -127,6 +137,44 @@ namespace boost }; } + namespace detail // deduce_char_traits template + { +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct deduce_char_traits + { + typedef std::char_traits type; + }; + + template + struct deduce_char_traits< CharT + , std::basic_string + , Source + > + { + typedef Traits type; + }; + + template + struct deduce_char_traits< CharT + , Target + , std::basic_string + > + { + typedef Traits type; + }; + + template + struct deduce_char_traits< CharT + , std::basic_string + , std::basic_string + > + { + typedef Traits type; + }; +#endif + } + namespace detail // lcast_src_length { // Return max. length of string representation of Source; @@ -309,8 +357,6 @@ namespace boost #undef BOOST_AUX_LEXICAL_CAST_DEF1 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION -// This #if is in sync with lcast_precision - // Helper for floating point types. // -1.23456789e-123456 // ^ sign @@ -450,9 +496,7 @@ namespace boost namespace detail // lcast_put_unsigned { - // I'd personally put lcast_put_unsigned in .cpp file if not - // boost practice for header-only libraries (Alexander Nasonov). - template + template CharT* lcast_put_unsigned(T n, CharT* finish) { #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS @@ -482,6 +526,9 @@ namespace boost #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); #endif + typedef typename Traits::int_type int_type; + CharT const czero = lcast_char_constants::zero; + int_type const zero = Traits::to_int_type(czero); char left = last_grp_size; @@ -498,14 +545,13 @@ namespace boost left = last_grp_size; --finish; - *finish = thousands_sep; + Traits::assign(*finish, thousands_sep); } --left; --finish; - int const digit = static_cast(n % 10); - int const cdigit = digit + lcast_char_constants::zero; - *finish = static_cast(cdigit); + int_type const digit = static_cast(n % 10U); + Traits::assign(*finish, Traits::to_char_type(zero + digit)); n /= 10; } while(n); @@ -515,7 +561,7 @@ namespace boost namespace detail // stream wrapper for handling lexical conversions { - template + template class lexical_stream { private: @@ -523,6 +569,8 @@ namespace boost typename stream_char::type, typename stream_char::type>::type char_type; + typedef Traits traits_type; + public: lexical_stream(char_type* = 0, char_type* = 0) { @@ -552,9 +600,12 @@ namespace boost EOF; #else - std::char_traits::eof(); + traits_type::eof(); #endif } + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + bool operator>>(std::string &output) { #if defined(BOOST_NO_STRINGSTREAM) @@ -570,13 +621,29 @@ namespace boost return true; } #endif + +#else + bool operator>>(std::basic_string& output) + { + stream.str().swap(output); + return true; + } + + template + bool operator>>(std::basic_string& out) + { + std::basic_string str(stream.str()); + out.assign(str.begin(), str.end()); + return true; + } +#endif private: #if defined(BOOST_NO_STRINGSTREAM) std::strstream stream; #elif defined(BOOST_NO_STD_LOCALE) std::stringstream stream; #else - std::basic_stringstream stream; + std::basic_stringstream stream; #endif }; } @@ -586,6 +653,7 @@ namespace boost // String representation of Source has an upper limit. template< class CharT // a result of widest_char transformation , class Base // lexical_streambuf_fake or basic_streambuf + , class Traits // usually char_traits > class lexical_stream_limited_src : public Base { @@ -599,19 +667,20 @@ namespace boost static void widen_and_assign(char*p, char ch) { - *p = ch; + Traits::assign(*p, ch); } #ifndef DISABLE_WIDE_CHAR_SUPPORT static void widen_and_assign(wchar_t* p, char ch) { std::locale loc; - *p = BOOST_USE_FACET(std::ctype, loc).widen(ch); + wchar_t w = BOOST_USE_FACET(std::ctype, loc).widen(ch); + Traits::assign(*p, w); } static void widen_and_assign(wchar_t* p, wchar_t ch) { - *p = ch; + Traits::assign(*p, ch); } static void widen_and_assign(char*, wchar_t ch); // undefined @@ -641,8 +710,8 @@ namespace boost public: // output - template - bool operator<<(std::basic_string const& str) + template + bool operator<<(std::basic_string const& str) { start = const_cast(str.data()); finish = start + str.length(); @@ -705,7 +774,7 @@ namespace boost EOF; #else - std::char_traits::eof(); + Traits::eof(); #endif } @@ -721,7 +790,7 @@ namespace boost #endif #else - template + template bool operator>>(std::basic_string& str) { str.assign(start, finish); @@ -730,17 +799,21 @@ namespace boost #endif }; - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( bool value) { - *start = value + lcast_char_constants::zero; + typedef typename Traits::int_type int_type; + CharT const czero = lcast_char_constants::zero; + int_type const zero = Traits::to_int_type(czero); + Traits::assign(*start, Traits::to_char_type(zero + value)); finish = start + 1; return true; } - template - inline bool lexical_stream_limited_src::operator<<(char ch) + template + inline bool lexical_stream_limited_src::operator<<( + char ch) { widen_and_assign(start, ch); finish = start + 1; @@ -748,8 +821,8 @@ namespace boost } #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( wchar_t ch) { widen_and_assign(start, ch); @@ -758,140 +831,163 @@ namespace boost } #endif - template - inline bool lexical_stream_limited_src::operator<<(short n) + template + inline bool lexical_stream_limited_src::operator<<( + short n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) - *--start = lcast_char_constants::minus; + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } return true; } - template - inline bool lexical_stream_limited_src::operator<<(int n) + template + inline bool lexical_stream_limited_src::operator<<( + int n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) - *--start = lcast_char_constants::minus; + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } return true; } - template - inline bool lexical_stream_limited_src::operator<<(long n) + template + inline bool lexical_stream_limited_src::operator<<( + long n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) - *--start = lcast_char_constants::minus; + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } return true; } #if defined(BOOST_HAS_LONG_LONG) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( boost::long_long_type n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) - *--start = lcast_char_constants::minus; + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } return true; } #elif defined(BOOST_HAS_MS_INT64) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( __int64 n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); if(n < 0) - *--start = lcast_char_constants::minus; + { + --start; + CharT const minus = lcast_char_constants::minus; + Traits::assign(*start, minus); + } return true; } #endif - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned short n) { - start = lcast_put_unsigned(lcast_to_unsigned(n), finish); + start = lcast_put_unsigned(lcast_to_unsigned(n), finish); return true; } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned int n) { - start = lcast_put_unsigned(n, finish); + start = lcast_put_unsigned(n, finish); return true; } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned long n) { - start = lcast_put_unsigned(n, finish); + start = lcast_put_unsigned(n, finish); return true; } #if defined(BOOST_HAS_LONG_LONG) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( boost::ulong_long_type n) { - start = lcast_put_unsigned(n, finish); + start = lcast_put_unsigned(n, finish); return true; } #elif defined(BOOST_HAS_MS_INT64) - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( unsigned __int64 n) { - start = lcast_put_unsigned(n, finish); + start = lcast_put_unsigned(n, finish); return true; } #endif - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( float val) { return this->lcast_put(val); } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( double val) { return this->lcast_put(val); } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( long double val) { return this->lcast_put(val); } - template - inline bool lexical_stream_limited_src::operator<<( + template + inline bool lexical_stream_limited_src::operator<<( CharT const* str) { start = const_cast(str); - finish = start + std::char_traits::length(str); + finish = start + Traits::length(str); return true; } - template - inline bool lexical_stream_limited_src::operator>>( + template + inline bool lexical_stream_limited_src::operator>>( CharT& output) { bool const ok = (finish - start == 1); if(ok) - output = *start; + Traits::assign(output, *start); return ok; } #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - inline bool lexical_stream_limited_src::operator>>( + template + inline bool lexical_stream_limited_src::operator>>( std::string& str) { str.assign(start, finish); @@ -899,8 +995,8 @@ namespace boost } #ifndef DISABLE_WIDE_CHAR_SUPPORT - template - inline bool lexical_stream_limited_src::operator>>( + template + inline bool lexical_stream_limited_src::operator>>( std::wstring& str) { str.assign(start, finish); @@ -1021,6 +1117,12 @@ namespace boost BOOST_DEDUCED_TYPENAME boost::call_traits::param_type arg, CharT* buf, std::size_t src_len) { +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + typedef BOOST_DEDUCED_TYPENAME + deduce_char_traits::type traits; +#else + typedef std::char_traits traits; +#endif typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< lcast_streambuf_for_target::value || lcast_streambuf_for_source::value @@ -1030,8 +1132,8 @@ namespace boost BOOST_DEDUCED_TYPENAME boost::mpl::if_c< Unlimited - , detail::lexical_stream - , detail::lexical_stream_limited_src + , detail::lexical_stream + , detail::lexical_stream_limited_src >::type interpreter(buf, buf + src_len); // The original form, reproduced below, is more elegant diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 6ba26a3..04478e0 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -24,6 +24,9 @@ #include #include +#include +#include + #if defined(BOOST_NO_STRINGSTREAM) || \ defined(BOOST_NO_STD_WSTRING) || \ defined(BOOST_NO_STD_LOCALE) @@ -35,6 +38,16 @@ #define LCAST_TEST_LONGLONG #endif +template +struct my_traits : std::char_traits +{ +}; + +template +struct my_allocator : std::allocator +{ +}; + // Test all 65536 values if true: bool const lcast_test_small_integral_types_completely = false; @@ -57,15 +70,21 @@ void test_conversion_from_wstring(); void test_conversion_to_wstring(); void test_bad_lexical_cast(); void test_no_whitespace_stripping(); -void test_conversion_from_short(); -void test_conversion_from_ushort(); -void test_conversion_from_int(); -void test_conversion_from_uint(); -void test_conversion_from_long(); -void test_conversion_from_ulong(); +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_longlong(); -void test_conversion_from_ulonglong(); +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 *[]) @@ -87,15 +106,21 @@ 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_short)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_ushort)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_int)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_uint)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_ulong)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_long)); + 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_longlong)); - suite->add(BOOST_TEST_CASE(&test_conversion_from_ulonglong)); + 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; @@ -129,10 +154,15 @@ void test_conversion_to_int() BOOST_CHECK_EQUAL(0, lexical_cast('0')); BOOST_CHECK_THROW(lexical_cast('A'), bad_lexical_cast); BOOST_CHECK_EQUAL(1, lexical_cast(1)); + BOOST_CHECK_EQUAL(1, lexical_cast(1.0)); + BOOST_CHECK_EQUAL( (std::numeric_limits::max)(), lexical_cast((std::numeric_limits::max)())); - BOOST_CHECK_EQUAL(1, lexical_cast(1.0)); + + BOOST_CHECK_EQUAL( + (std::numeric_limits::min)(), + lexical_cast((std::numeric_limits::min)())); BOOST_CHECK_THROW(lexical_cast(1.23), bad_lexical_cast); @@ -407,7 +437,7 @@ void test_conversion_from_integral_to_char(CharT zero) BOOST_CHECK_THROW(lexical_cast(static_cast(10)), bad_lexical_cast); - T t = std::numeric_limits::max(); + T t = (std::numeric_limits::max)(); BOOST_CHECK_THROW(lexical_cast(t), bad_lexical_cast); } @@ -427,10 +457,10 @@ void test_conversion_from_integral_to_integral() BOOST_CHECK(lexical_cast(t) == st); BOOST_CHECK(lexical_cast(t) == ut); - t = std::numeric_limits::max(); + t = (std::numeric_limits::max)(); BOOST_CHECK(lexical_cast(t) == t); - t = std::numeric_limits::min(); + t = (std::numeric_limits::min)(); BOOST_CHECK(lexical_cast(t) == t); } @@ -442,19 +472,20 @@ void test_conversion_from_integral_to_string(CharT) T t; - t = limits::min(); + t = (limits::min)(); BOOST_CHECK(lexical_cast(t) == to_str(t)); - t = limits::max(); + t = (limits::max)(); BOOST_CHECK(lexical_cast(t) == to_str(t)); if(limits::digits <= 16 && lcast_test_small_integral_types_completely) - for(t = 1 + limits::min(); t != limits::max(); ++t) + // min and max have already been tested. + for(t = 1 + (limits::min)(); t != (limits::max)(); ++t) BOOST_CHECK(lexical_cast(t) == to_str(t)); else { - T const min_val = limits::min(); - T const max_val = limits::max(); + 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; @@ -480,20 +511,75 @@ void test_conversion_from_integral_to_string(CharT) T ten_power = 100; for(int e = 2; e <= limits::digits10; ++e, ten_power *= 10) { - // I believe that (ten_power + 100) never overflows + // ten_power + 100 probably never overflows for(t = ten_power - 100; t != ten_power + 100; ++t) BOOST_CHECK(lexical_cast(t) == to_str(t)); } } } +template +void test_conversion_from_string_to_integral(CharT) +{ + typedef std::numeric_limits limits; + + T t; + + t = (limits::min)(); + BOOST_CHECK(lexical_cast(to_str(t)) == t); + + t = (limits::max)(); + BOOST_CHECK(lexical_cast(to_str(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(to_str(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(to_str(t)) == t); + + // Test values around max: + t = max_val; + for(i = 0; i < counter; ++i, --t) + BOOST_CHECK(lexical_cast(to_str(t)) == t); + + // Test values around zero: + if(limits::is_signed) + for(t = -counter; t < static_cast(counter); ++t) + BOOST_CHECK(lexical_cast(to_str(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(to_str(t)) == t); + } + } +} + template -void test_conversion_from_integral_for_locale() +void test_conversion_from_to_integral_for_locale() { test_conversion_from_integral_to_integral(); test_conversion_from_integral_to_string('0'); + test_conversion_from_string_to_integral('0'); #if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) test_conversion_from_integral_to_string(L'0'); + test_conversion_from_string_to_integral(L'0'); #endif } @@ -504,7 +590,7 @@ struct restore_oldloc }; template -void test_conversion_from_integral() +void test_conversion_from_to_integral() { char const zero = '0'; signed char const szero = '0'; @@ -517,7 +603,7 @@ void test_conversion_from_integral() test_conversion_from_integral_to_char(wzero); #endif - // test_conversion_from_integral_for_locale + // test_conversion_from_to_integral_for_locale typedef std::numpunct numpunct; @@ -527,7 +613,7 @@ void test_conversion_from_integral() std::string grouping1 = BOOST_USE_FACET(numpunct, oldloc).grouping(); std::string grouping2(grouping1); - test_conversion_from_integral_for_locale(); + test_conversion_from_to_integral_for_locale(); try { @@ -544,64 +630,121 @@ void test_conversion_from_integral() } if(grouping1 != grouping2) - test_conversion_from_integral_for_locale(); + test_conversion_from_to_integral_for_locale(); if(grouping1.empty() && grouping2.empty()) BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested"); } -void test_conversion_from_short() +void test_conversion_from_to_short() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_ushort() +void test_conversion_from_to_ushort() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_int() +void test_conversion_from_to_int() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_uint() +void test_conversion_from_to_uint() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_ulong() +void test_conversion_from_to_ulong() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_long() +void test_conversion_from_to_long() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } #if defined(BOOST_HAS_LONG_LONG) -void test_conversion_from_longlong() +void test_conversion_from_to_longlong() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } -void test_conversion_from_ulonglong() +void test_conversion_from_to_ulonglong() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); } #elif defined(LCAST_TEST_LONGLONG) -void test_conversion_from_longlong() +void test_conversion_from_to_longlong() { - test_conversion_from_integral<__int64>(); + test_conversion_from_to_integral<__int64>(); } -void test_conversion_from_ulonglong() +void test_conversion_from_to_ulonglong() { - test_conversion_from_integral(); + test_conversion_from_to_integral(); +} + +#endif + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +void test_traits() +{ + typedef std::basic_string > my_string; + + my_string const s("s"); + BOOST_CHECK(boost::lexical_cast(s) == s[0]); + BOOST_CHECK(boost::lexical_cast(s) == s); + BOOST_CHECK(boost::lexical_cast(-1) == "-1"); +} + +void test_wtraits() +{ + typedef std::basic_string > my_string; + + my_string const s(L"s"); + BOOST_CHECK(boost::lexical_cast(s) == s[0]); + BOOST_CHECK(boost::lexical_cast(s) == s); + //BOOST_CHECK(boost::lexical_cast(-1) == L"-1"); + // Commented out because gcc 3.3 doesn't support this: + // basic_ostream > o; o << -1; +} + +void test_allocator() +{ + typedef std::basic_string< char + , std::char_traits + , my_allocator + > my_string; + + my_string s("s"); + BOOST_CHECK(boost::lexical_cast(s) == s[0]); + BOOST_CHECK(boost::lexical_cast(s) == "s"); + BOOST_CHECK(boost::lexical_cast(s) == s); + BOOST_CHECK(boost::lexical_cast(1) == "1"); + BOOST_CHECK(boost::lexical_cast("s") == s); + BOOST_CHECK(boost::lexical_cast(std::string("s")) == s); +} + +void test_wallocator() +{ + typedef std::basic_string< wchar_t + , std::char_traits + , my_allocator + > my_string; + + my_string s(L"s"); + BOOST_CHECK(boost::lexical_cast(s) == s[0]); + BOOST_CHECK(boost::lexical_cast(s) == L"s"); + BOOST_CHECK(boost::lexical_cast(s) == s); + BOOST_CHECK(boost::lexical_cast(1) == L"1"); + BOOST_CHECK(boost::lexical_cast(L"s") == s); + BOOST_CHECK(boost::lexical_cast(std::wstring(L"s")) == s); } #endif