diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 280de8a..3986f00 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -2060,26 +2060,35 @@ namespace boost { template struct lexical_converter_impl { - static inline bool try_convert(const Source& arg, Target& result) - { - typedef lexical_cast_stream_traits stream_trait; - - typedef detail::lexical_istream_limited_src< - BOOST_DEDUCED_TYPENAME stream_trait::char_type, - BOOST_DEDUCED_TYPENAME stream_trait::traits, - stream_trait::requires_stringbuf, - stream_trait::len_t::value + 1 - > i_interpreter_type; + typedef lexical_cast_stream_traits stream_trait; - typedef detail::lexical_ostream_limited_src< - BOOST_DEDUCED_TYPENAME stream_trait::char_type, - BOOST_DEDUCED_TYPENAME stream_trait::traits - > o_interpreter_type; + typedef detail::lexical_istream_limited_src< + BOOST_DEDUCED_TYPENAME stream_trait::char_type, + BOOST_DEDUCED_TYPENAME stream_trait::traits, + stream_trait::requires_stringbuf, + stream_trait::len_t::value + 1 + > i_interpreter_type; + typedef detail::lexical_ostream_limited_src< + BOOST_DEDUCED_TYPENAME stream_trait::char_type, + BOOST_DEDUCED_TYPENAME stream_trait::traits + > o_interpreter_type; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + static inline bool try_convert(T&& arg, Target& result) { + typedef T&& forward_type; +#else + static inline bool try_convert(const Source& arg, Target& result) { + typedef const Source& forward_type; +#endif i_interpreter_type i_interpreter; // Disabling ADL, by directly specifying operators. - if (!(i_interpreter.operator <<(arg))) + // + // For compilers with perfect forwarding `static_cast(arg)` is + // eqaul to `std::forward(arg)`. + if (!(i_interpreter.operator <<(static_cast(arg)))) return false; o_interpreter_type out(i_interpreter.cbegin(), i_interpreter.cend()); @@ -2095,11 +2104,18 @@ namespace boost { template struct copy_converter_impl { - static inline bool try_convert(const Source& arg, Target& result) - { +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + static inline bool try_convert(T&& arg, Target& result) { + result = static_cast(arg); // eqaul to `result = std::forward(arg);` + return true; + } +#else + static inline bool try_convert(const Source& arg, Target& result) { result = arg; return true; } +#endif }; template @@ -2146,12 +2162,20 @@ namespace boost { } }; - template - inline bool stateful_numeric_convert(const Source& arg, Target& result) BOOST_NOEXCEPT { + template + inline bool noexcept_numeric_convert(const Source& arg, Target& result) BOOST_NOEXCEPT { + typedef boost::numeric::converter< + Target, + Source, + boost::numeric::conversion_traits, + nothrow_overflow_handler, + detect_precision_loss + > converter_orig_t; + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< - boost::is_base_of< detect_precision_loss, Converter >::value, - Converter, - fake_precision_loss + boost::is_base_of< detect_precision_loss, converter_orig_t >::value, + converter_orig_t, + fake_precision_loss >::type converter_t; bool res = nothrow_overflow_handler()(converter_t::out_of_range(arg)); @@ -2162,43 +2186,27 @@ namespace boost { template struct lexical_cast_dynamic_num_not_ignoring_minus { - static inline bool try_convert(const Source &arg, Target& result) BOOST_NOEXCEPT - { - return stateful_numeric_convert, - nothrow_overflow_handler, - detect_precision_loss - > >(arg, result); + static inline bool try_convert(const Source &arg, Target& result) BOOST_NOEXCEPT { + return noexcept_numeric_convert(arg, result); } }; template struct lexical_cast_dynamic_num_ignoring_minus { - static inline bool try_convert(const Source &arg, Target& result) BOOST_NOEXCEPT - { + static inline bool try_convert(const Source &arg, Target& result) BOOST_NOEXCEPT { typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if_c< boost::is_float::value, boost::mpl::identity, boost::make_unsigned >::type usource_t; - - typedef boost::numeric::converter< - Target, - usource_t, - boost::numeric::conversion_traits, - nothrow_overflow_handler, - detect_precision_loss - > converter_t; if (arg < 0) { - const bool res = stateful_numeric_convert(0u - arg, result); + const bool res = noexcept_numeric_convert(0u - arg, result); result = static_cast(0u - result); return res; } else { - return stateful_numeric_convert(arg, result); + return noexcept_numeric_convert(arg, result); } } }; @@ -2224,8 +2232,7 @@ namespace boost { template struct dynamic_num_converter_impl { - static inline bool try_convert(const Source &arg, Target& result) BOOST_NOEXCEPT - { + static inline bool try_convert(const Source &arg, Target& result) BOOST_NOEXCEPT { typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< boost::type_traits::ice_and< boost::is_unsigned::value, @@ -2250,10 +2257,23 @@ namespace boost { } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template - inline bool try_lexical_cast(const Source &arg, Target& result) + inline bool try_lexical_convert(Source&& arg, Target& result) { - typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay::type src; + typedef BOOST_DEDUCED_TYPENAME boost::remove_const< + BOOST_DEDUCED_TYPENAME boost::remove_reference::type + >::type no_cr_source_t; + + typedef Source&& forward_type; +#else + template + inline bool try_lexical_convert(const Source& arg, Target& result) + { + typedef Source no_cr_source_t; + typedef const Source& forward_type; +#endif + 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, @@ -2285,7 +2305,7 @@ namespace boost { typedef BOOST_DEDUCED_TYPENAME caster_type_lazy::type caster_type; - return caster_type::try_convert(arg, result); + return caster_type::try_convert(static_cast(arg), result); } template @@ -2293,7 +2313,7 @@ namespace boost { { Target result; - if (!try_lexical_cast(arg, result)) + if (!try_lexical_convert(arg, result)) BOOST_LCAST_THROW_BAD_CAST(Source, Target); return result; @@ -2308,9 +2328,9 @@ namespace boost { } template - inline bool try_lexical_cast(const char* chars, std::size_t count, Target& result) + inline bool try_lexical_convert(const char* chars, std::size_t count, Target& result) { - return ::boost::try_lexical_cast( + return ::boost::try_lexical_convert( ::boost::iterator_range(chars, chars + count), result ); } @@ -2324,9 +2344,9 @@ namespace boost { } template - inline bool try_lexical_cast(const unsigned char* chars, std::size_t count, Target& result) + inline bool try_lexical_convert(const unsigned char* chars, std::size_t count, Target& result) { - return ::boost::try_lexical_cast( + return ::boost::try_lexical_convert( ::boost::iterator_range(chars, chars + count), result ); } @@ -2340,9 +2360,9 @@ namespace boost { } template - inline bool try_lexical_cast(const signed char* chars, std::size_t count, Target& result) + inline bool try_lexical_convert(const signed char* chars, std::size_t count, Target& result) { - return ::boost::try_lexical_cast( + return ::boost::try_lexical_convert( ::boost::iterator_range(chars, chars + count), result ); } @@ -2357,9 +2377,9 @@ namespace boost { } template - inline bool try_lexical_cast(const wchar_t* chars, std::size_t count, Target& result) + inline bool try_lexical_convert(const wchar_t* chars, std::size_t count, Target& result) { - return ::boost::try_lexical_cast( + return ::boost::try_lexical_convert( ::boost::iterator_range(chars, chars + count), result ); } @@ -2374,9 +2394,9 @@ namespace boost { } template - inline bool try_lexical_cast(const char16_t* chars, std::size_t count, Target& result) + inline bool try_lexical_convert(const char16_t* chars, std::size_t count, Target& result) { - return ::boost::try_lexical_cast( + return ::boost::try_lexical_convert( ::boost::iterator_range(chars, chars + count), result ); } @@ -2391,9 +2411,9 @@ namespace boost { } template - inline bool try_lexical_cast(const char32_t* chars, std::size_t count, Target& result) + inline bool try_lexical_convert(const char32_t* chars, std::size_t count, Target& result) { - return ::boost::try_lexical_cast( + return ::boost::try_lexical_convert( ::boost::iterator_range(chars, chars + count), result ); }