diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index c475982..4cb4041 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -162,6 +162,8 @@ namespace boost #include #include #include +#include +#include #include #include #include @@ -171,236 +173,331 @@ namespace boost #endif namespace boost { - namespace detail // widest_char<...> (continuation) - { - struct not_a_character_type{}; - template - struct widest_char - { - typedef CharT type; - }; - - template - struct widest_char< CharT, not_a_character_type > - { - typedef CharT type; - }; - - template <> - struct widest_char< not_a_character_type, not_a_character_type > - { - typedef char type; - }; - } - - namespace detail // is_char_or_wchar<...> and stream_char<...> templates + namespace detail // is_char_or_wchar<...> { // returns true, if T is one of the character types - template + template < typename T > struct is_char_or_wchar { - typedef ::boost::type_traits::ice_or< - ::boost::is_same< T, char >::value, + typedef boost::type_traits::ice_or< + boost::is_same< T, char >::value, #ifndef BOOST_LCAST_NO_WCHAR_T - ::boost::is_same< T, wchar_t >::value, + boost::is_same< T, wchar_t >::value, #endif #ifndef BOOST_NO_CHAR16_T - ::boost::is_same< T, char16_t >::value, + boost::is_same< T, char16_t >::value, #endif #ifndef BOOST_NO_CHAR32_T - ::boost::is_same< T, char32_t >::value, + boost::is_same< T, char32_t >::value, #endif - ::boost::is_same< T, unsigned char >::value, - ::boost::is_same< T, signed char >::value + boost::is_same< T, unsigned char >::value, + boost::is_same< T, signed char >::value > result_type; BOOST_STATIC_CONSTANT(bool, value = (result_type::value) ); }; + } - // selectors for choosing stream character type - // returns one of char, wchar_t, char16_t, char32_t or not_a_character_type types - template - struct stream_char + namespace detail // normalize_single_byte_char + { + // Converts signed/unsigned char to char + template < class Char > + struct normalize_single_byte_char { - typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< - is_char_or_wchar::value, - Type, - boost::detail::not_a_character_type - >::type type; + typedef Char type; }; template <> - struct stream_char + struct normalize_single_byte_char< signed char > { typedef char type; }; template <> - struct stream_char + struct normalize_single_byte_char< unsigned char > { typedef char type; }; + } - template - struct stream_char - { - typedef BOOST_DEDUCED_TYPENAME stream_char::type type; - }; + namespace detail // deduce_character_type_later + { + // Helper type, meaning that stram character for T must be deduced + // at Stage 2 (See deduce_source_char and deduce_target_char) + template < class T > struct deduce_character_type_later {}; + } - template - struct stream_char - { - typedef BOOST_DEDUCED_TYPENAME stream_char::type type; - }; + namespace detail // stream_char_common + { + // Selectors to choose stream character type (common for Source and Target) + // Returns one of char, wchar_t, char16_t, char32_t or deduce_character_type_later types + // Executed on Stage 1 (See deduce_source_char and deduce_target_char) + template < typename Type > + struct stream_char_common: public boost::mpl::if_c< + boost::detail::is_char_or_wchar< Type >::value, + Type, + boost::detail::deduce_character_type_later< Type > + > {}; - template - struct stream_char > - { - typedef BOOST_DEDUCED_TYPENAME stream_char::type type; - }; + template < typename Char > + struct stream_char_common< Char* >: public boost::mpl::if_c< + boost::detail::is_char_or_wchar< Char >::value, + Char, + boost::detail::deduce_character_type_later< Char* > + > {}; + + template < typename Char > + struct stream_char_common< const Char* >: public boost::mpl::if_c< + boost::detail::is_char_or_wchar< Char >::value, + Char, + boost::detail::deduce_character_type_later< const Char* > + > {}; + + template < typename Char > + struct stream_char_common< boost::iterator_range< Char* > >: public boost::mpl::if_c< + boost::detail::is_char_or_wchar< Char >::value, + Char, + boost::detail::deduce_character_type_later< boost::iterator_range< Char* > > + > {}; - template - struct stream_char > + template < typename Char > + struct stream_char_common< boost::iterator_range< const Char* > >: public boost::mpl::if_c< + boost::detail::is_char_or_wchar< Char >::value, + Char, + boost::detail::deduce_character_type_later< boost::iterator_range< const Char* > > + > {}; + + template < class Char, class Traits, class Alloc > + struct stream_char_common< std::basic_string< Char, Traits, Alloc > > { - typedef BOOST_DEDUCED_TYPENAME stream_char::type type; + typedef Char type; }; - template - struct stream_char< std::basic_string > + template < class Char, class Traits, class Alloc > + struct stream_char_common< boost::container::basic_string< Char, Traits, Alloc > > { - typedef CharT type; + typedef Char type; }; - template - struct stream_char< ::boost::container::basic_string > - { - typedef CharT type; - }; + template < typename Char, std::size_t N > + struct stream_char_common< boost::array< Char, N > >: public boost::mpl::if_c< + boost::detail::is_char_or_wchar< Char >::value, + Char, + boost::detail::deduce_character_type_later< boost::array< Char, N > > + > {}; - template - struct stream_char > - { - typedef BOOST_DEDUCED_TYPENAME stream_char::type type; - }; - - template - struct stream_char > - { - typedef BOOST_DEDUCED_TYPENAME stream_char::type type; - }; + template < typename Char, std::size_t N > + struct stream_char_common< boost::array< const Char, N > >: public boost::mpl::if_c< + boost::detail::is_char_or_wchar< Char >::value, + Char, + boost::detail::deduce_character_type_later< boost::array< const Char, N > > + > {}; #if !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) - template - struct stream_char > - { - typedef BOOST_DEDUCED_TYPENAME stream_char::type type; - }; + template < typename Char, std::size_t N > + struct stream_char_common< std::array >: public boost::mpl::if_c< + boost::detail::is_char_or_wchar< Char >::value, + Char, + boost::detail::deduce_character_type_later< std::array< Char, N > > + > {}; - template - struct stream_char > - { - typedef BOOST_DEDUCED_TYPENAME stream_char::type type; - }; + template < typename Char, std::size_t N > + struct stream_char_common< std::array< const Char, N > >: public boost::mpl::if_c< + boost::detail::is_char_or_wchar< Char >::value, + Char, + boost::detail::deduce_character_type_later< std::array< const Char, N > > + > {}; #endif // !defined(BOOST_NO_CXX11_HDR_ARRAY) && defined(BOOST_HAS_TR1_ARRAY) #if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T) - template<> - struct stream_char + template <> + struct stream_char_common< wchar_t > { - typedef boost::detail::not_a_character_type type; - }; - - template<> - struct stream_char - { - typedef wchar_t type; - }; - - template<> - struct stream_char - { - typedef wchar_t type; + typedef char type; }; #endif } + namespace detail // deduce_source_char_impl + { + // If type T is `deduce_character_type_later` type, then tries to deduce + // character type using boost::has_left_shift metafunction. + // Otherwise supplied type T is a character type, that must be normalized + // using normalize_single_byte_char. + // Executed at Stage 2 (See deduce_source_char and deduce_target_char) + template < class Char > + struct deduce_source_char_impl + { + typedef BOOST_DEDUCED_TYPENAME boost::detail::normalize_single_byte_char< Char >::type type; + }; + + template < class T > + struct deduce_source_char_impl< deduce_character_type_later< T > > + { + typedef boost::has_left_shift< std::basic_ostream< char >, T > result_t; + +#if defined(BOOST_LCAST_NO_WCHAR_T) + BOOST_STATIC_ASSERT_MSG((result_t::value), + "Source type is not std::ostream`able and std::wostream`s are not supported by your STL implementation"); + typedef char type; +#else + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< + result_t::value, char, wchar_t + >::type type; + + BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_left_shift< std::basic_ostream< type >, T >::value), + "Source type is neither std::ostream`able nor std::wostream`able"); +#endif + }; + } + + namespace detail // deduce_target_char_impl + { + // If type T is `deduce_character_type_later` type, then tries to deduce + // character type using boost::has_right_shift metafunction. + // Otherwise supplied type T is a character type, that must be normalized + // using normalize_single_byte_char. + // Executed at Stage 2 (See deduce_source_char and deduce_target_char) + template < class Char > + struct deduce_target_char_impl + { + typedef BOOST_DEDUCED_TYPENAME normalize_single_byte_char< Char >::type type; + }; + + template < class T > + struct deduce_target_char_impl< deduce_character_type_later > + { + typedef boost::has_right_shift, T > result_t; + +#if defined(BOOST_LCAST_NO_WCHAR_T) + BOOST_STATIC_ASSERT_MSG((result_t::value), + "Target type is not std::istream`able and std::wistream`s are not supported by your STL implementation"); + typedef char type; +#else + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< + result_t::value, char, wchar_t + >::type type; + + BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift, T >::value), + "Target type is neither std::istream`able nor std::wistream`able"); +#endif + }; + } + + namespace detail // deduce_target_char and deduce_source_char + { + // We deduce stream character types in two stages. + // + // Stage 1 is common for Target and Source. At Stage 1 we get + // non normalized character type (may contain unsigned/signed char) + // or deduce_character_type_later where T is the original type. + // Stage 1 is executed by stream_char_common + // + // At Stage 2 we normalize character types or try to deduce character + // type using metafunctions. + // Stage 2 is executed by deduce_target_char_impl and + // deduce_source_char_impl + // + // deduce_target_char and deduce_source_char functions combine + // both stages + + template < class T > + struct deduce_target_char + { + typedef BOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type; + typedef BOOST_DEDUCED_TYPENAME deduce_target_char_impl< stage1_type >::type stage2_type; + + typedef stage2_type type; + }; + + template < class T > + struct deduce_source_char + { + typedef BOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type; + typedef BOOST_DEDUCED_TYPENAME deduce_source_char_impl< stage1_type >::type stage2_type; + + typedef stage2_type type; + }; + } + namespace detail // deduce_char_traits template { - - template + // We are attempting to get char_traits<> from Source or Tagret + // template parameter. Otherwise we'll be using std::char_traits + template < class Char, class Target, class Source > struct deduce_char_traits { - typedef std::char_traits type; + typedef std::char_traits< Char > type; }; - template - struct deduce_char_traits< CharT - , std::basic_string + template < class Char, class Traits, class Alloc, class Source > + struct deduce_char_traits< Char + , std::basic_string< Char, Traits, Alloc > , Source > { typedef Traits type; }; - template - struct deduce_char_traits< CharT + template < class Char, class Target, class Traits, class Alloc > + struct deduce_char_traits< Char , Target - , std::basic_string + , std::basic_string< Char, Traits, Alloc > > { typedef Traits type; }; - template - struct deduce_char_traits< CharT - , ::boost::container::basic_string + template < class Char, class Traits, class Alloc, class Source > + struct deduce_char_traits< Char + , boost::container::basic_string< Char, Traits, Alloc > , Source > { typedef Traits type; }; - template - struct deduce_char_traits< CharT + template < class Char, class Target, class Traits, class Alloc > + struct deduce_char_traits< Char , Target - , ::boost::container::basic_string + , boost::container::basic_string< Char, Traits, Alloc > > { typedef Traits type; }; - template - struct deduce_char_traits< CharT - , std::basic_string - , std::basic_string + template < class Char, class Traits, class Alloc1, class Alloc2 > + struct deduce_char_traits< Char + , std::basic_string< Char, Traits, Alloc1 > + , std::basic_string< Char, Traits, Alloc2 > > { typedef Traits type; }; - template - struct deduce_char_traits< CharT - , ::boost::container::basic_string - , ::boost::container::basic_string + template + struct deduce_char_traits< Char + , boost::container::basic_string< Char, Traits, Alloc1 > + , boost::container::basic_string< Char, Traits, Alloc2 > > { typedef Traits type; }; - template - struct deduce_char_traits< CharT - , ::boost::container::basic_string - , ::std::basic_string + template < class Char, class Traits, class Alloc1, class Alloc2 > + struct deduce_char_traits< Char + , boost::container::basic_string< Char, Traits, Alloc1 > + , std::basic_string< Char, Traits, Alloc2 > > { typedef Traits type; }; - template - struct deduce_char_traits< CharT - , ::std::basic_string - , ::boost::container::basic_string + template < class Char, class Traits, class Alloc1, class Alloc2 > + struct deduce_char_traits< Char + , std::basic_string< Char, Traits, Alloc1 > + , boost::container::basic_string< Char, Traits, Alloc2 > > { typedef Traits type; @@ -518,7 +615,7 @@ namespace boost { namespace detail // '0', '+' and '-' constants { - template struct lcast_char_constants; + template < typename Char > struct lcast_char_constants; template<> struct lcast_char_constants @@ -1247,7 +1344,7 @@ namespace boost { typedef std::basic_ostringstream out_stream_t; typedef stl_buf_unlocker, CharT> unlocked_but_t; #endif - typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< RequiresStringbuffer, out_stream_t, do_not_construct_out_stream_t @@ -1288,7 +1385,7 @@ namespace boost { std::locale loc; CharT const w = BOOST_USE_FACET(std::ctype, loc).widen(ch); #else - CharT const w = ch; + CharT const w = static_cast(ch); #endif Traits::assign(*start, w); finish = start + 1; @@ -1439,7 +1536,7 @@ namespace boost { } template - bool operator<<(::boost::container::basic_string const& str) BOOST_NOEXCEPT + bool operator<<(boost::container::basic_string const& str) BOOST_NOEXCEPT { start = const_cast(str.data()); finish = start + str.length(); @@ -1777,7 +1874,7 @@ namespace boost { bool operator>>(std::basic_string& str) { str.assign(start, finish); return true; } template - bool operator>>(::boost::container::basic_string& str) { str.assign(start, finish); return true; } + bool operator>>(boost::container::basic_string& str) { str.assign(start, finish); return true; } private: @@ -1917,7 +2014,7 @@ namespace boost { * */ boost::mpl::if_c< #if defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64) - ::boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value, + boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value, #else 0 #endif @@ -1968,7 +2065,7 @@ namespace boost { }; template - struct is_stdstring< ::boost::container::basic_string > + struct is_stdstring< boost::container::basic_string > { BOOST_STATIC_CONSTANT(bool, value = true ); }; @@ -1978,13 +2075,13 @@ namespace boost { { BOOST_STATIC_CONSTANT(bool, value = ( - ::boost::type_traits::ice_and< - ::boost::is_arithmetic::value, - ::boost::is_arithmetic::value, - ::boost::type_traits::ice_not< + boost::type_traits::ice_and< + boost::is_arithmetic::value, + boost::is_arithmetic::value, + boost::type_traits::ice_not< detail::is_char_or_wchar::value >::value, - ::boost::type_traits::ice_not< + boost::type_traits::ice_not< detail::is_char_or_wchar::value >::value >::value @@ -2002,14 +2099,14 @@ namespace boost { { BOOST_STATIC_CONSTANT(bool, value = ( - ::boost::type_traits::ice_or< - ::boost::type_traits::ice_and< + boost::type_traits::ice_or< + boost::type_traits::ice_and< is_same::value, is_char_or_wchar::value >::value, - ::boost::type_traits::ice_and< - ::boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value, - ::boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value, + boost::type_traits::ice_and< + boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value, + boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value, is_char_or_wchar::value, is_char_or_wchar::value >::value @@ -2025,15 +2122,15 @@ namespace boost { template struct is_this_float_conversion_optimized { - typedef ::boost::type_traits::ice_and< - ::boost::is_float::value, + typedef boost::type_traits::ice_and< + boost::is_float::value, #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) - ::boost::type_traits::ice_or< - ::boost::type_traits::ice_eq::value, - ::boost::is_same::value + boost::type_traits::ice_or< + boost::type_traits::ice_eq::value, + boost::is_same::value >::value #else - ::boost::type_traits::ice_eq::value + boost::type_traits::ice_eq::value #endif > result_type; @@ -2059,13 +2156,13 @@ namespace boost { }; template - struct is_char_array_to_stdstring< ::boost::container::basic_string, CharT* > + struct is_char_array_to_stdstring< boost::container::basic_string, CharT* > { BOOST_STATIC_CONSTANT(bool, value = true ); }; template - struct is_char_array_to_stdstring< ::boost::container::basic_string, const CharT* > + struct is_char_array_to_stdstring< boost::container::basic_string, const CharT* > { BOOST_STATIC_CONSTANT(bool, value = true ); }; @@ -2081,51 +2178,58 @@ namespace boost { { static inline Target lexical_cast_impl(const Source& arg) { - typedef BOOST_DEDUCED_TYPENAME detail::array_to_pointer_decay::type src; - typedef BOOST_DEDUCED_TYPENAME ::boost::remove_cv::type no_cv_src; - typedef BOOST_DEDUCED_TYPENAME detail::stream_char::type target_char_t; - typedef BOOST_DEDUCED_TYPENAME detail::stream_char::type src_char_type; - typedef BOOST_DEDUCED_TYPENAME detail::widest_char< - target_char_t, src_char_type + typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay::type src; + typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cv_src; + + typedef boost::detail::deduce_source_char deduce_src_char_metafunc; + typedef BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::type src_char_t; + typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_target_char::type target_char_t; + + typedef BOOST_DEDUCED_TYPENAME boost::detail::widest_char< + target_char_t, src_char_t >::type char_type; #if !defined(BOOST_NO_CHAR16_T) && defined(BOOST_NO_UNICODE_LITERALS) - BOOST_STATIC_ASSERT_MSG(( !::boost::is_same::value - && !::boost::is_same::value), + BOOST_STATIC_ASSERT_MSG(( !boost::is_same::value + && !boost::is_same::value), "Your compiler does not have full support for char16_t" ); #endif #if !defined(BOOST_NO_CHAR32_T) && defined(BOOST_NO_UNICODE_LITERALS) - BOOST_STATIC_ASSERT_MSG(( !::boost::is_same::value - && !::boost::is_same::value), + BOOST_STATIC_ASSERT_MSG(( !boost::is_same::value + && !boost::is_same::value), "Your compiler does not have full support for char32_t" ); #endif - typedef BOOST_DEDUCED_TYPENAME ::boost::detail::deduce_char_traits< + typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_char_traits< char_type, Target, no_cv_src >::type traits; - typedef ::boost::type_traits::ice_and< - ::boost::detail::is_char_or_wchar::value, // source is lexical type - ::boost::detail::is_char_or_wchar::value, // target is a lexical type - ::boost::is_same::value, // source is not a wide character based type - ::boost::type_traits::ice_ne::value // target type is based on wide character + typedef boost::type_traits::ice_and< + boost::is_same::value, // source is not a wide character based type + boost::type_traits::ice_ne::value, // target type is based on wide character + boost::type_traits::ice_not< + boost::detail::is_char_or_wchar::value // single character widening is optimized + >::value // and does not requires stringbuffer > is_string_widening_required_t; - typedef ::boost::type_traits::ice_or< - ::boost::is_integral::value, - ::boost::detail::is_this_float_conversion_optimized::value, - ::boost::detail::is_char_or_wchar::value - > is_source_input_optimized_t; + typedef boost::type_traits::ice_not< boost::type_traits::ice_or< + boost::is_integral::value, + boost::detail::is_this_float_conversion_optimized::value, + boost::detail::is_char_or_wchar< + BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::stage1_type // if we did not get character type at stage1 + >::value // then we have no optimization for that type + >::value > is_source_input_not_optimized_t; // Target type must be default constructible Target result; // If we have an optimized conversion for // Source, we do not need to construct stringbuf. - const bool requires_stringbuf = ::boost::type_traits::ice_or< - is_string_widening_required_t::value, - ::boost::type_traits::ice_not< is_source_input_optimized_t::value >::value - >::value; + BOOST_STATIC_CONSTANT(bool, requires_stringbuf = + (boost::type_traits::ice_or< + is_string_widening_required_t::value, is_source_input_not_optimized_t::value + >::value) + ); typedef detail::lexical_stream_limited_src interpreter_type; @@ -2163,7 +2267,7 @@ namespace boost { typedef Source source_type ; typedef BOOST_DEDUCED_TYPENAME mpl::if_< - ::boost::is_arithmetic, Source, Source const& + boost::is_arithmetic, Source, Source const& >::type argument_type ; static source_type nearbyint ( argument_type s ) @@ -2247,19 +2351,19 @@ namespace boost { { static inline Target lexical_cast_impl(const Source &arg) { - typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< - ::boost::type_traits::ice_and< - ::boost::type_traits::ice_or< - ::boost::is_signed::value, - ::boost::is_float::value + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< + boost::type_traits::ice_and< + boost::type_traits::ice_or< + boost::is_signed::value, + boost::is_float::value >::value, - ::boost::type_traits::ice_not< - ::boost::is_same::value + boost::type_traits::ice_not< + boost::is_same::value >::value, - ::boost::type_traits::ice_not< - ::boost::is_same::value + boost::type_traits::ice_not< + boost::is_same::value >::value, - ::boost::is_unsigned::value + boost::is_unsigned::value >::value, lexical_cast_dynamic_num_ignoring_minus, lexical_cast_dynamic_num_not_ignoring_minus @@ -2273,86 +2377,44 @@ namespace boost { template inline Target lexical_cast(const Source &arg) { - typedef BOOST_DEDUCED_TYPENAME ::boost::detail::array_to_pointer_decay::type src; + typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay::type src; - typedef BOOST_DEDUCED_TYPENAME ::boost::type_traits::ice_or< - ::boost::detail::is_xchar_to_xchar::value, - ::boost::detail::is_char_array_to_stdstring::value, - ::boost::type_traits::ice_and< - ::boost::is_same::value, - ::boost::detail::is_stdstring::value + typedef BOOST_DEDUCED_TYPENAME boost::type_traits::ice_or< + boost::detail::is_xchar_to_xchar::value, + boost::detail::is_char_array_to_stdstring::value, + boost::type_traits::ice_and< + boost::is_same::value, + boost::detail::is_stdstring::value >::value > shall_we_copy_t; typedef BOOST_DEDUCED_TYPENAME - ::boost::detail::is_arithmetic_and_not_xchars shall_we_copy_with_dynamic_check_t; + boost::detail::is_arithmetic_and_not_xchars shall_we_copy_with_dynamic_check_t; - typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< shall_we_copy_t::value, - ::boost::detail::lexical_cast_copy, - BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< + boost::detail::lexical_cast_copy, + BOOST_DEDUCED_TYPENAME boost::mpl::if_c< shall_we_copy_with_dynamic_check_t::value, - ::boost::detail::lexical_cast_dynamic_num, - ::boost::detail::lexical_cast_do_cast + boost::detail::lexical_cast_dynamic_num, + boost::detail::lexical_cast_do_cast >::type >::type caster_type; return caster_type::lexical_cast_impl(arg); } - template - inline Target lexical_cast(const char* chars, std::size_t count) + template + inline Target lexical_cast(const CharType* chars, std::size_t count) { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) - ); - } + BOOST_STATIC_ASSERT_MSG(boost::detail::is_char_or_wchar::value, + "CharType must be a character or wide character type"); - - template - inline Target lexical_cast(const unsigned char* chars, std::size_t count) - { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) + return boost::lexical_cast( + boost::iterator_range(chars, chars + count) ); } - template - inline Target lexical_cast(const signed char* chars, std::size_t count) - { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) - ); - } - -#ifndef BOOST_LCAST_NO_WCHAR_T - template - inline Target lexical_cast(const wchar_t* chars, std::size_t count) - { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) - ); - } -#endif -#ifndef BOOST_NO_CHAR16_T - template - inline Target lexical_cast(const char16_t* chars, std::size_t count) - { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) - ); - } -#endif -#ifndef BOOST_NO_CHAR32_T - template - inline Target lexical_cast(const char32_t* chars, std::size_t count) - { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) - ); - } -#endif - } // namespace boost #else // #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f77a845..633368f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -49,5 +49,6 @@ test-suite conversion [ run lexical_cast_iterator_range_test.cpp ] [ run lexical_cast_arrays_test.cpp ] [ run lexical_cast_integral_types_test.cpp ] + [ run lexical_cast_stream_detection_test.cpp ] ; diff --git a/test/lexical_cast_stream_detection_test.cpp b/test/lexical_cast_stream_detection_test.cpp new file mode 100644 index 0000000..82bc562 --- /dev/null +++ b/test/lexical_cast_stream_detection_test.cpp @@ -0,0 +1,307 @@ +// 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 +#include + +#include + +#include + + +///////////////////////// char streamable classes /////////////////////////////////////////// + +struct streamable_easy { enum ENU {value = 0}; }; +std::ostream& operator << (std::ostream& ostr, const streamable_easy&) { + return ostr << streamable_easy::value; +} +std::istream& operator >> (std::istream& istr, const streamable_easy&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_easy::value); + return istr; +} + +struct streamable_medium { enum ENU {value = 1}; }; +template +typename boost::enable_if, std::basic_ostream&>::type +operator << (std::basic_ostream& ostr, const streamable_medium&) { + return ostr << streamable_medium::value; +} +template +typename boost::enable_if, std::basic_istream&>::type +operator >> (std::basic_istream& istr, const streamable_medium&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_medium::value); + return istr; +} + +struct streamable_hard { enum ENU {value = 2}; }; +template +typename boost::enable_if, std::basic_ostream&>::type +operator << (std::basic_ostream& ostr, const streamable_hard&) { + return ostr << streamable_hard::value; +} +template +typename boost::enable_if, std::basic_istream&>::type +operator >> (std::basic_istream& istr, const streamable_hard&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard::value); + return istr; +} + +struct streamable_hard2 { enum ENU {value = 3}; }; +template +std::basic_ostream& operator << (std::basic_ostream& ostr, const streamable_hard2&) { + return ostr << streamable_hard2::value; +} +template +std::basic_istream& operator >> (std::basic_istream& istr, const streamable_hard2&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard2::value); + return istr; +} + + +///////////////////////// wchar_t streamable classes /////////////////////////////////////////// + +struct wstreamable_easy { enum ENU {value = 4}; }; +std::wostream& operator << (std::wostream& ostr, const wstreamable_easy&) { + return ostr << wstreamable_easy::value; +} +std::wistream& operator >> (std::wistream& istr, const wstreamable_easy&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_easy::value); + return istr; +} + +struct wstreamable_medium { enum ENU {value = 5}; }; +template +typename boost::enable_if, std::basic_ostream& >::type +operator << (std::basic_ostream& ostr, const wstreamable_medium&) { + return ostr << wstreamable_medium::value; +} +template +typename boost::enable_if, std::basic_istream& >::type +operator >> (std::basic_istream& istr, const wstreamable_medium&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_medium::value); + return istr; +} + +struct wstreamable_hard { enum ENU {value = 6}; }; +template +typename boost::enable_if, std::basic_ostream&>::type +operator << (std::basic_ostream& ostr, const wstreamable_hard&) { + return ostr << wstreamable_hard::value; +} +template +typename boost::enable_if, std::basic_istream&>::type +operator >> (std::basic_istream& istr, const wstreamable_hard&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard::value); + return istr; +} + +struct wstreamable_hard2 { enum ENU {value = 7}; }; +template +std::basic_ostream& operator << (std::basic_ostream& ostr, const wstreamable_hard2&) { + return ostr << wstreamable_hard2::value; +} +template +std::basic_istream& operator >> (std::basic_istream& istr, const wstreamable_hard2&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard2::value); + return istr; +} + +///////////////////////// char and wchar_t streamable classes /////////////////////////////////////////// + + +struct bistreamable_easy { enum ENU {value = 8}; }; +std::ostream& operator << (std::ostream& ostr, const bistreamable_easy&) { + return ostr << bistreamable_easy::value; +} +std::istream& operator >> (std::istream& istr, const bistreamable_easy&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value); + return istr; +} + +std::wostream& operator << (std::wostream& ostr, const bistreamable_easy&) { + return ostr << bistreamable_easy::value + 100; +} +std::wistream& operator >> (std::wistream& istr, const bistreamable_easy&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value + 100); + return istr; +} + +struct bistreamable_medium { enum ENU {value = 9}; }; +template +std::basic_ostream& operator << (std::basic_ostream& ostr, const bistreamable_medium&) { + return ostr << bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100); +} +template +std::basic_istream& operator >> (std::basic_istream& istr, const bistreamable_medium&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100)); + return istr; +} + +struct bistreamable_hard { enum ENU {value = 10}; }; +template +std::basic_ostream& operator << (std::basic_ostream& ostr, const bistreamable_hard&) { + return ostr << bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100); +} +template +std::basic_istream& operator >> (std::basic_istream& istr, const bistreamable_hard&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100)); + return istr; +} + +struct bistreamable_hard2 { enum ENU {value = 11}; }; +template +std::basic_ostream& operator << (std::basic_ostream& ostr, const bistreamable_hard2&) { + return ostr << bistreamable_hard2::value; +} +template +std::basic_istream& operator >> (std::basic_istream& istr, const bistreamable_hard2&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value); + return istr; +} + +template +std::basic_ostream& operator << (std::basic_ostream& ostr, const bistreamable_hard2&) { + return ostr << bistreamable_hard2::value + 100; +} +template +std::basic_istream& operator >> (std::basic_istream& istr, const bistreamable_hard2&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value + 100); + return istr; +} + + +void test_ostream_character_detection(); +void test_istream_character_detection(); +void test_mixed_stream_character_detection(); + +boost::unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + boost::unit_test::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast stream character detection"); + suite->add(BOOST_TEST_CASE(&test_ostream_character_detection)); + suite->add(BOOST_TEST_CASE(&test_istream_character_detection)); + suite->add(BOOST_TEST_CASE(&test_mixed_stream_character_detection)); + + return suite; +} + +template +static void test_ostr_impl() { + T streamable; + BOOST_CHECK_EQUAL(T::value, boost::lexical_cast(streamable)); + BOOST_CHECK_EQUAL(boost::lexical_cast(T::value), boost::lexical_cast(streamable)); +} + +template +static void test_wostr_impl() { + T streamable; + BOOST_CHECK_EQUAL(T::value, boost::lexical_cast(streamable)); + // BOOST_CHECK_EQUAL(boost::lexical_cast(T::value), boost::lexical_cast(streamable)); // Shall not compile??? + BOOST_CHECK(boost::lexical_cast(T::value) == boost::lexical_cast(streamable)); +} + +template +static void test_bistr_impl() { + T streamable; + + BOOST_CHECK_EQUAL(T::value, boost::lexical_cast(streamable)); + BOOST_CHECK_EQUAL(boost::lexical_cast(T::value), boost::lexical_cast(streamable)); + + BOOST_CHECK(boost::lexical_cast(T::value + 100) == boost::lexical_cast(streamable)); +} + +void test_ostream_character_detection() { + test_ostr_impl(); + test_ostr_impl(); + test_ostr_impl(); + test_ostr_impl(); + + test_wostr_impl(); + test_wostr_impl(); + test_wostr_impl(); + test_wostr_impl(); + + test_bistr_impl(); + test_bistr_impl(); + test_bistr_impl(); + test_bistr_impl(); +} + + +template +static void test_istr_impl() { + boost::lexical_cast(T::value); + boost::lexical_cast(boost::lexical_cast(T::value)); +} + +template +static void test_wistr_impl() { + boost::lexical_cast(T::value); + //boost::lexical_cast(boost::lexical_cast(T::value)); // Shall not compile??? + boost::lexical_cast(boost::lexical_cast(T::value)); +} + +template +static void test_bistr_instr_impl() { + boost::lexical_cast(T::value); + boost::lexical_cast(boost::lexical_cast(T::value)); + boost::lexical_cast(boost::lexical_cast(T::value + 100)); +} + +void test_istream_character_detection() { + test_istr_impl(); + test_istr_impl(); + test_istr_impl(); + test_istr_impl(); + + test_wistr_impl(); + test_wistr_impl(); + test_wistr_impl(); + test_wistr_impl(); + + test_bistr_instr_impl(); + test_bistr_instr_impl(); + test_bistr_instr_impl(); + test_bistr_instr_impl(); +} + + + + + + +struct wistreamble_ostreamable { enum ENU {value = 200}; }; +std::ostream& operator << (std::ostream& ostr, const wistreamble_ostreamable&) { + return ostr << wistreamble_ostreamable::value; +} +std::wistream& operator >> (std::wistream& istr, const wistreamble_ostreamable&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, wistreamble_ostreamable::value); + return istr; +} + +struct istreamble_wostreamable { enum ENU {value = 201}; }; +std::wostream& operator << (std::wostream& ostr, const istreamble_wostreamable&) { + return ostr << istreamble_wostreamable::value; +} +std::istream& operator >> (std::istream& istr, const istreamble_wostreamable&) { + int i; istr >> i; BOOST_CHECK_EQUAL(i, istreamble_wostreamable::value); + return istr; +} + +void test_mixed_stream_character_detection() { + //boost::lexical_cast(std::string("qwe")); // TODO: ALLOW IT AS EXTENSION! + + boost::lexical_cast(wistreamble_ostreamable::value); + BOOST_CHECK_EQUAL(boost::lexical_cast(wistreamble_ostreamable()), wistreamble_ostreamable::value); + + boost::lexical_cast(istreamble_wostreamable::value); + BOOST_CHECK_EQUAL(boost::lexical_cast(istreamble_wostreamable()), istreamble_wostreamable::value); +}