Merge from trunk:

1) #warning replaced with #error (refs #7228)
2) Pavel Korzh added to thanks list (refs #7157)
3) BOOST_NOEXCEPT modifiers added where possible
4) better support for c++11 Unicode characters
5) fixed compilation with MSVC+STLPort
6) more agressive usage of Traits template parameter
7) Added lexical_cast(const CharType* chars, std::size_t count) function overload (refs #6430 and refs #6663)
8) Fixed GCC warning in numeric_cast_test.cpp
9) Fix compilation of lexical cast with MSVC 2003 (refs #7255)

[SVN r80409]
This commit is contained in:
Antony Polukhin
2012-09-05 18:23:41 +00:00
parent f67347e308
commit 733438e072
5 changed files with 147 additions and 85 deletions

View File

@@ -79,6 +79,13 @@ Following example converts some number and puts it to file:
buf_t buffer = boost::lexical_cast<buf_t>(i); // No dynamic memory allocation
puts(buffer.begin(), file);
``
Following example takes part of the string and converts it to `int`:
``
int convert_strings_part(const std::string& s, std::size_t pos, std::size_t n)
{
return boost::lexical_cast<int>(s.data() + pos, n);
}
``
[endsect]
[section Synopsis]
@@ -99,7 +106,13 @@ Library features defined in [@boost:boost/lexical_cast.hpp boost/lexical_cast.hp
``
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:
``
template <typename Target, typename CharType>
Target lexical_cast(const CharType* chars, std::size_t count);
``
Takes an array of `count` characters as input parameter and streams them out as a Target object. If the conversion is unsuccessful, a `bad_lexical_cast` exception is thrown. This call may be useful for processing nonzero terminated array of characters or processing just some part of character array.
The requirements on the argument and result types for both functions 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.
@@ -114,6 +127,7 @@ The character type of the underlying stream is assumed to be `char` unless eithe
* `boost::iterator_range<WideCharPtr>`, where `WideCharPtr` is a pointer to wide-character or pointer to const wide-character
* `boost::array<CharT, N>` and `std::array<CharT, N>`, `boost::array<const CharT, N>` and `std::array<const CharT, N>`
[important Many compilers and runtime libraries fail to make conversions using new Unicode characters. Make sure that the following code compiles and outputs nonzero values, before using new types:
``
std::cout
@@ -253,12 +267,17 @@ limitation of compiler options that you use.
]
* [*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));`.
* [*Answer:] Use `boost::iterator_range` for conversion or `lexical_cast` overload with two parameters. For example, if you whant to convert to `int` two characters from a string `str`, you shall write `lexical_cast<int>(make_iterator_range(str.data(), str.data() + 2));` or `lexical_cast<int>(str.data(), 2);`.
[endsect]
[section Changes]
* [*boost 1.52.0 :]
* Restored compilation on MSVC-2003 (was broken in 1.51.0).
* Added `lexical_cast(const CharType* chars, std::size_t count)` function overload.
* [*boost 1.51.0 :]
* Better performance, less memory usage for `boost::array<character_type, N>` and `std::array<character_type, N>` conversions.

View File

@@ -18,7 +18,7 @@
// with additional fixes and suggestions from Gennaro Prota,
// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
// Cheng Yang, Matthew Bradbury, David W. Birdsall and other Boosters
// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2012
#include <boost/config.hpp>
@@ -47,8 +47,12 @@
# include <locale>
#else
# ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
# warning "Unable to use <locale> header. boost::lexical_cast will use the 'C' locale."
# define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
// Getting error at this point means, that your STL library is old/lame/misconfigured.
// If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE,
// but beware: lexical_cast will understand only 'C' locale delimeters and thousands
// separators.
# error "Unable to use <locale> header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force "
# error "boost::lexical_cast to use only 'C' locale during conversions."
# endif
#endif
@@ -83,7 +87,7 @@ namespace boost
{
public:
bad_lexical_cast() :
bad_lexical_cast() BOOST_NOEXCEPT :
#ifndef BOOST_NO_TYPEID
source(&typeid(void)), target(&typeid(void))
#else
@@ -94,7 +98,7 @@ namespace boost
bad_lexical_cast(
const std::type_info &source_type_arg,
const std::type_info &target_type_arg) :
const std::type_info &target_type_arg) BOOST_NOEXCEPT :
source(&source_type_arg), target(&target_type_arg)
{
}
@@ -108,14 +112,22 @@ namespace boost
return *target;
}
#ifndef BOOST_NO_NOEXCEPT
virtual const char *what() const noexcept
#else
virtual const char *what() const throw()
#endif
{
return "bad lexical cast: "
"source type value could not be interpreted as target";
}
#ifndef BOOST_NO_NOEXCEPT
virtual ~bad_lexical_cast() BOOST_NOEXCEPT
#else
virtual ~bad_lexical_cast() throw()
{
}
#endif
{}
private:
const std::type_info *source;
const std::type_info *target;
@@ -570,10 +582,10 @@ namespace boost {
#endif
template<class T>
inline
BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value)
BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value) BOOST_NOEXCEPT
{
typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type;
result_type uvalue = static_cast<result_type>(value);
const result_type uvalue = static_cast<result_type>(value);
return value < 0 ? -uvalue : uvalue;
}
#if (defined _MSC_VER)
@@ -777,7 +789,7 @@ namespace boost {
namespace detail
{
template <class CharT>
bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) {
bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) BOOST_NOEXCEPT {
for( unsigned int i=0; i < len; ++i ) {
if ( val[i] != lcase[i] && val[i] != ucase[i] ) return false;
}
@@ -790,7 +802,7 @@ namespace boost {
inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value
, const CharT* lc_NAN, const CharT* lc_nan
, const CharT* lc_INFINITY, const CharT* lc_infinity
, const CharT opening_brace, const CharT closing_brace)
, const CharT opening_brace, const CharT closing_brace) BOOST_NOEXCEPT
{
using namespace std;
if (begin == end) return false;
@@ -846,7 +858,7 @@ namespace boost {
template <class CharT, class T>
bool put_inf_nan_impl(CharT* begin, CharT*& end, const T& value
, const CharT* lc_nan
, const CharT* lc_infinity)
, const CharT* lc_infinity) BOOST_NOEXCEPT
{
using namespace std;
const CharT minus = lcast_char_constants<CharT>::minus;
@@ -880,7 +892,7 @@ namespace boost {
#ifndef BOOST_LCAST_NO_WCHAR_T
template <class T>
bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value)
bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) BOOST_NOEXCEPT
{
return parse_inf_nan_impl(begin, end, value
, L"NAN", L"nan"
@@ -889,7 +901,7 @@ namespace boost {
}
template <class T>
bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value)
bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) BOOST_NOEXCEPT
{
return put_inf_nan_impl(begin, end, value, L"nan", L"infinity");
}
@@ -897,7 +909,7 @@ namespace boost {
#endif
#if !defined(BOOST_NO_CHAR16_T) && !defined(BOOST_NO_UNICODE_LITERALS)
template <class T>
bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value)
bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) BOOST_NOEXCEPT
{
return parse_inf_nan_impl(begin, end, value
, u"NAN", u"nan"
@@ -906,14 +918,14 @@ namespace boost {
}
template <class T>
bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value)
bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value) BOOST_NOEXCEPT
{
return put_inf_nan_impl(begin, end, value, u"nan", u"infinity");
}
#endif
#if !defined(BOOST_NO_CHAR32_T) && !defined(BOOST_NO_UNICODE_LITERALS)
template <class T>
bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value)
bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) BOOST_NOEXCEPT
{
return parse_inf_nan_impl(begin, end, value
, U"NAN", U"nan"
@@ -922,14 +934,14 @@ namespace boost {
}
template <class T>
bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value)
bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value) BOOST_NOEXCEPT
{
return put_inf_nan_impl(begin, end, value, U"nan", U"infinity");
}
#endif
template <class CharT, class T>
bool parse_inf_nan(const CharT* begin, const CharT* end, T& value)
bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) BOOST_NOEXCEPT
{
return parse_inf_nan_impl(begin, end, value
, "NAN", "nan"
@@ -938,7 +950,7 @@ namespace boost {
}
template <class CharT, class T>
bool put_inf_nan(CharT* begin, CharT*& end, const T& value)
bool put_inf_nan(CharT* begin, CharT*& end, const T& value) BOOST_NOEXCEPT
{
return put_inf_nan_impl(begin, end, value, "nan", "infinity");
}
@@ -1008,11 +1020,11 @@ namespace boost {
/* Getting the plus/minus sign */
bool has_minus = false;
if ( *begin == minus ) {
if (Traits::eq(*begin, minus) ) {
++ begin;
has_minus = true;
if (begin == end) return false;
} else if ( *begin == plus ) {
} else if (Traits::eq(*begin, plus) ) {
++begin;
if (begin == end) return false;
}
@@ -1031,7 +1043,7 @@ namespace boost {
/* We allow no thousand_separators after decimal point */
mantissa_type tmp_mantissa = mantissa * 10u;
if ( *begin == lowercase_e || *begin == capital_e ) break;
if (Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) break;
if ( *begin < czero || *begin >= czero + 10 ) return false;
if ( is_mantissa_full
|| tmp_mantissa / 10u != mantissa
@@ -1070,7 +1082,7 @@ namespace boost {
found_number_before_exp = true;
++ length_since_last_delim;
} else if ( *begin == decimal_point || *begin == lowercase_e || *begin == capital_e) {
} else if (Traits::eq(*begin, decimal_point) || Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) {
#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
/* If ( we need to check grouping
* and ( grouping missmatches
@@ -1088,7 +1100,7 @@ namespace boost {
) return false;
#endif
if(*begin == decimal_point) {
if(Traits::eq(*begin, decimal_point)) {
++ begin;
found_decimal = true;
if (!found_number_before_exp && begin==end) return false;
@@ -1099,7 +1111,7 @@ namespace boost {
}
}
#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
else if (grouping_size && *begin == thousands_sep){
else if (grouping_size && Traits::eq(*begin, thousands_sep)){
if(found_grouping)
{
/* It is not he first time, when we find thousands separator,
@@ -1141,16 +1153,16 @@ namespace boost {
}
// Exponent found
if ( begin != end && ( *begin == lowercase_e || *begin == capital_e ) ) {
if ( begin != end && (Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) ) {
++ begin;
if ( begin == end ) return false;
bool exp_has_minus = false;
if( *begin == minus ) {
if(Traits::eq(*begin, minus)) {
exp_has_minus = true;
++ begin;
if ( begin == end ) return false;
} else if (*begin == plus ) {
} else if (Traits::eq(*begin, plus)) {
++ begin;
if ( begin == end ) return false;
}
@@ -1258,7 +1270,7 @@ namespace boost {
void operator=(lexical_stream_limited_src const&);
/************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/
bool shl_char(CharT ch)
bool shl_char(CharT ch) BOOST_NOEXCEPT
{
Traits::assign(*start, ch);
finish = start + 1;
@@ -1270,13 +1282,13 @@ namespace boost {
bool shl_char(T ch)
{
BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) ,
"boost::lexical_cast does not support conversions from wide character to char types."
"boost::lexical_cast does not support narrowing of char types."
"Use boost::locale instead" );
#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
std::locale loc;
wchar_t w = BOOST_USE_FACET(std::ctype<wchar_t>, loc).widen(ch);
CharT const w = BOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch);
#else
wchar_t w = ch;
CharT const w = ch;
#endif
Traits::assign(*start, w);
finish = start + 1;
@@ -1284,7 +1296,7 @@ namespace boost {
}
#endif
bool shl_char_array(CharT const* str)
bool shl_char_array(CharT const* str) BOOST_NOEXCEPT
{
start = const_cast<CharT*>(str);
finish = start + Traits::length(str);
@@ -1295,15 +1307,15 @@ namespace boost {
bool shl_char_array(T const* str)
{
BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)),
"boost::lexical_cast does not support conversions from wide characters to char types."
"boost::lexical_cast does not support narrowing of char types."
"Use boost::locale instead" );
return shl_input_streamable(str);
}
bool shl_char_array_limited(CharT const* str, std::size_t max_size)
bool shl_char_array_limited(CharT const* str, std::size_t max_size) BOOST_NOEXCEPT
{
start = const_cast<CharT*>(str);
finish = std::find(start, start + max_size, static_cast<CharT>(0));
finish = std::find(start, start + max_size, Traits::to_char_type(0));
return true;
}
@@ -1349,7 +1361,7 @@ namespace boost {
if (put_inf_nan(begin, end, val)) return true;
const double val_as_double = val;
end = begin +
#if (defined _MSC_VER)
#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
sprintf_s(begin, end-begin,
#else
sprintf(begin,
@@ -1362,7 +1374,7 @@ namespace boost {
{ using namespace std;
if (put_inf_nan(begin, end, val)) return true;
end = begin +
#if (defined _MSC_VER)
#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
sprintf_s(begin, end-begin,
#else
sprintf(begin,
@@ -1376,7 +1388,7 @@ namespace boost {
{ using namespace std;
if (put_inf_nan(begin, end, val)) return true;
end = begin +
#if (defined _MSC_VER)
#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
sprintf_s(begin, end-begin,
#else
sprintf(begin,
@@ -1419,7 +1431,7 @@ namespace boost {
/************************************ OPERATORS << ( ... ) ********************************/
public:
template<class Alloc>
bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT
{
start = const_cast<CharT*>(str.data());
finish = start + str.length();
@@ -1427,14 +1439,14 @@ namespace boost {
}
template<class Alloc>
bool operator<<(::boost::container::basic_string<CharT,Traits,Alloc> const& str)
bool operator<<(::boost::container::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT
{
start = const_cast<CharT*>(str.data());
finish = start + str.length();
return true;
}
bool operator<<(bool value)
bool operator<<(bool value) BOOST_NOEXCEPT
{
CharT const czero = lcast_char_constants<CharT>::zero;
Traits::assign(*start, Traits::to_char_type(czero + value));
@@ -1442,21 +1454,21 @@ namespace boost {
return true;
}
bool operator<<(const iterator_range<CharT*>& rng)
bool operator<<(const iterator_range<CharT*>& rng) BOOST_NOEXCEPT
{
start = rng.begin();
finish = rng.end();
return true;
}
bool operator<<(const iterator_range<const CharT*>& rng)
bool operator<<(const iterator_range<const CharT*>& rng) BOOST_NOEXCEPT
{
start = const_cast<CharT*>(rng.begin());
finish = const_cast<CharT*>(rng.end());
return true;
}
bool operator<<(const iterator_range<const signed char*>& rng)
bool operator<<(const iterator_range<const signed char*>& rng) BOOST_NOEXCEPT
{
return (*this) << iterator_range<char*>(
const_cast<char*>(reinterpret_cast<const char*>(rng.begin())),
@@ -1464,7 +1476,7 @@ namespace boost {
);
}
bool operator<<(const iterator_range<const unsigned char*>& rng)
bool operator<<(const iterator_range<const unsigned char*>& rng) BOOST_NOEXCEPT
{
return (*this) << iterator_range<char*>(
const_cast<char*>(reinterpret_cast<const char*>(rng.begin())),
@@ -1472,7 +1484,7 @@ namespace boost {
);
}
bool operator<<(const iterator_range<signed char*>& rng)
bool operator<<(const iterator_range<signed char*>& rng) BOOST_NOEXCEPT
{
return (*this) << iterator_range<char*>(
reinterpret_cast<char*>(rng.begin()),
@@ -1480,7 +1492,7 @@ namespace boost {
);
}
bool operator<<(const iterator_range<unsigned char*>& rng)
bool operator<<(const iterator_range<unsigned char*>& rng) BOOST_NOEXCEPT
{
return (*this) << iterator_range<char*>(
reinterpret_cast<char*>(rng.begin()),
@@ -1539,52 +1551,52 @@ namespace boost {
}
template <std::size_t N>
bool operator<<(boost::array<CharT, N> const& input)
bool operator<<(boost::array<CharT, N> const& input) BOOST_NOEXCEPT
{ return shl_char_array_limited(input.begin(), N); }
template <std::size_t N>
bool operator<<(boost::array<unsigned char, N> const& input)
bool operator<<(boost::array<unsigned char, N> const& input) BOOST_NOEXCEPT
{ return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
template <std::size_t N>
bool operator<<(boost::array<signed char, N> const& input)
bool operator<<(boost::array<signed char, N> const& input) BOOST_NOEXCEPT
{ return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
template <std::size_t N>
bool operator<<(boost::array<const CharT, N> const& input)
bool operator<<(boost::array<const CharT, N> const& input) BOOST_NOEXCEPT
{ return shl_char_array_limited(input.begin(), N); }
template <std::size_t N>
bool operator<<(boost::array<const unsigned char, N> const& input)
bool operator<<(boost::array<const unsigned char, N> const& input) BOOST_NOEXCEPT
{ return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
template <std::size_t N>
bool operator<<(boost::array<const signed char, N> const& input)
bool operator<<(boost::array<const signed char, N> const& input) BOOST_NOEXCEPT
{ return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
template <std::size_t N>
bool operator<<(std::array<CharT, N> const& input)
bool operator<<(std::array<CharT, N> const& input) BOOST_NOEXCEPT
{ return shl_char_array_limited(input.begin(), N); }
template <std::size_t N>
bool operator<<(std::array<unsigned char, N> const& input)
bool operator<<(std::array<unsigned char, N> const& input) BOOST_NOEXCEPT
{ return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
template <std::size_t N>
bool operator<<(std::array<signed char, N> const& input)
bool operator<<(std::array<signed char, N> const& input) BOOST_NOEXCEPT
{ return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
template <std::size_t N>
bool operator<<(std::array<const CharT, N> const& input)
bool operator<<(std::array<const CharT, N> const& input) BOOST_NOEXCEPT
{ return shl_char_array_limited(input.begin(), N); }
template <std::size_t N>
bool operator<<(std::array<const unsigned char, N> const& input)
bool operator<<(std::array<const unsigned char, N> const& input) BOOST_NOEXCEPT
{ return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
template <std::size_t N>
bool operator<<(std::array<const signed char, N> const& input)
bool operator<<(std::array<const signed char, N> const& input) BOOST_NOEXCEPT
{ return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
#endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
@@ -1723,10 +1735,10 @@ namespace boost {
inline bool shr_xchar(T& output)
{
BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ),
"boost::lexical_cast does not support conversions from wchar_t to char types."
"boost::lexical_cast does not support narrowing of character types."
"Use boost::locale instead" );
bool const ok = (finish - start == 1);
if(ok) {
if (ok) {
CharT out;
Traits::assign(out, *start);
output = static_cast<T>(out);
@@ -1770,7 +1782,7 @@ namespace boost {
private:
template <std::size_t N, class ArrayT>
bool shr_std_array(ArrayT& output, boost::mpl::bool_<true> /*is_T_char_tag*/)
bool shr_std_array(ArrayT& output) BOOST_NOEXCEPT
{
using namespace std;
const std::size_t size = finish - start;
@@ -1779,22 +1791,16 @@ namespace boost {
}
memcpy(output.begin(), start, size * sizeof(CharT));
*(output.begin() + size) = static_cast<CharT>(0);
*(output.begin() + size) = Traits::to_char_type(0);
return true;
}
template <std::size_t N, class ArrayT>
bool shr_std_array(ArrayT& output, boost::mpl::bool_<false> /*is_T_char_tag*/)
{
return shr_using_base_class(output); // Array consist of non character types or unmatching character type
}
public:
template <std::size_t N>
bool operator>>(boost::array<CharT, N>& output)
bool operator>>(boost::array<CharT, N>& output) BOOST_NOEXCEPT
{
typedef boost::mpl::bool_<true> tag_type;
return shr_std_array<N>(output, tag_type());
return shr_std_array<N>(output);
}
template <std::size_t N>
@@ -1811,10 +1817,9 @@ namespace boost {
#if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY)
template <std::size_t N>
bool operator>>(std::array<CharT, N>& output)
bool operator>>(std::array<CharT, N>& output) BOOST_NOEXCEPT
{
typedef boost::mpl::bool_<true> tag_type;
return shr_std_array<N>(output, tag_type());
return shr_std_array<N>(output);
}
template <std::size_t N>
@@ -1836,7 +1841,7 @@ namespace boost {
* case "1" || "+1": output = true; return true;
* default: return false;
*/
bool operator>>(bool& output)
bool operator>>(bool& output) BOOST_NOEXCEPT
{
CharT const zero = lcast_char_constants<CharT>::zero;
CharT const plus = lcast_char_constants<CharT>::plus;
@@ -1886,10 +1891,10 @@ namespace boost {
CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
if ( return_value &&
(
*(finish-1) == lowercase_e // 1.0e
|| *(finish-1) == capital_e // 1.0E
|| *(finish-1) == minus // 1.0e- or 1.0E-
|| *(finish-1) == plus // 1.0e+ or 1.0E+
Traits::eq(*(finish-1), lowercase_e) // 1.0e
|| Traits::eq(*(finish-1), capital_e) // 1.0E
|| Traits::eq(*(finish-1), minus) // 1.0e- or 1.0E-
|| Traits::eq(*(finish-1), plus) // 1.0e+ or 1.0E+
)
) return false;
@@ -2145,7 +2150,7 @@ namespace boost {
template <typename Source>
struct lexical_cast_copy
{
static inline Source lexical_cast_impl(const Source &arg)
static inline const Source& lexical_cast_impl(const Source &arg) BOOST_NOEXCEPT
{
return arg;
}
@@ -2295,6 +2300,17 @@ namespace boost {
return caster_type::lexical_cast_impl(arg);
}
template <typename Target, typename CharType>
inline Target lexical_cast(const CharType* chars, std::size_t count)
{
BOOST_STATIC_ASSERT_MSG(::boost::detail::is_char_or_wchar<CharType>::value,
"CharType must be a character or wide character type");
return ::boost::lexical_cast<Target>(
::boost::iterator_range<const CharType*>(chars, chars + count)
);
}
} // namespace boost
#else // #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION

View File

@@ -73,6 +73,7 @@ void test_conversion_from_wstring();
void test_conversion_to_wstring();
void test_bad_lexical_cast();
void test_no_whitespace_stripping();
void test_volatile_types_conversions();
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
void test_traits();
void test_wtraits();
@@ -108,6 +109,7 @@ 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_volatile_types_conversions));
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
suite->add(BOOST_TEST_CASE(&test_traits));
suite->add(BOOST_TEST_CASE(&test_wtraits));
@@ -435,6 +437,17 @@ void test_no_whitespace_stripping()
BOOST_CHECK_THROW(lexical_cast<int>("123 "), bad_lexical_cast);
}
void test_volatile_types_conversions()
{
volatile int i1 = 100000;
BOOST_CHECK_EQUAL("100000", boost::lexical_cast<std::string>(i1));
volatile const int i2 = 100000;
BOOST_CHECK_EQUAL("100000", boost::lexical_cast<std::string>(i2));
volatile const long int i3 = 1000000;
BOOST_CHECK_EQUAL("1000000", boost::lexical_cast<std::string>(i3));
}
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
void test_traits()

View File

@@ -28,7 +28,7 @@ using namespace boost;
using std::cout;
int test_main( int argc, char * argv[] )
int test_main( int , char * [] )
{
# ifdef NDEBUG
@@ -96,5 +96,6 @@ int test_main( int argc, char * argv[] )
{ cout<<"caught bad_numeric_cast #5\n"; caught_exception = true; }
BOOST_CHECK ( caught_exception );
(void)ul; // Supressing GCC warning about set but unused wariable
return 0 ;
}

View File

@@ -46,24 +46,37 @@ 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<int>(rng.begin(), rng.size()), 1);
BOOST_CHECK_EQUAL(lexical_cast<unsigned int>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<unsigned int>(rng.begin(), rng.size()), 1u);
BOOST_CHECK_EQUAL(lexical_cast<short>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<short>(rng.begin(), rng.size()), 1);
BOOST_CHECK_EQUAL(lexical_cast<unsigned short>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<unsigned short>(rng.begin(), rng.size()), 1u);
BOOST_CHECK_EQUAL(lexical_cast<long int>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<long int>(rng.begin(), rng.size()), 1);
BOOST_CHECK_EQUAL(lexical_cast<unsigned long int>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<unsigned long int>(rng.begin(), rng.size()), 1u);
#ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES
BOOST_CHECK_EQUAL(lexical_cast<float>(rng), 1.0f);
BOOST_CHECK_EQUAL(lexical_cast<float>(rng.begin(), rng.size()), 1.0f);
BOOST_CHECK_EQUAL(lexical_cast<double>(rng), 1.0);
BOOST_CHECK_EQUAL(lexical_cast<double>(rng.begin(), rng.size()), 1.0);
BOOST_CHECK_EQUAL(lexical_cast<long double>(rng), 1.0L);
BOOST_CHECK_EQUAL(lexical_cast<long double>(rng.begin(), rng.size()), 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::ulong_long_type>(rng.begin(), rng.size()), 1u);
BOOST_CHECK_EQUAL(lexical_cast<boost::long_long_type>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<boost::long_long_type>(rng.begin(), rng.size()), 1);
#elif defined(BOOST_HAS_MS_INT64)
BOOST_CHECK_EQUAL(lexical_cast<unsigned __int64>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<unsigned __int64>(rng.begin(), rng.size()), 1u);
BOOST_CHECK_EQUAL(lexical_cast<__int64>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<__int64>(rng.begin(), rng.size()), 1);
#endif
}