diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 5b43501..1ae950d 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -2060,7 +2060,7 @@ namespace boost { template struct lexical_cast_do_cast { - static inline Target lexical_cast_impl(const Source& arg) + static inline bool try_lexical_cast_impl(const Source& arg, Target& result) { typedef lexical_cast_stream_traits stream_trait; @@ -2076,27 +2076,42 @@ namespace boost { BOOST_DEDUCED_TYPENAME stream_trait::traits > o_interpreter_type; - // Target type must be default constructible - Target result; - i_interpreter_type i_interpreter; // Disabling ADL, by directly specifying operators. - const bool input_ok = (i_interpreter.operator <<(arg)); + if (!(i_interpreter.operator <<(arg))) + return false; o_interpreter_type out(i_interpreter.cbegin(), i_interpreter.cend()); // Disabling ADL, by directly specifying operators. - if(!input_ok || !(out.operator >>(result))) - BOOST_LCAST_THROW_BAD_CAST(Source, Target); + if(!(out.operator >>(result))) + return false; + + return true; + } + + static inline Target lexical_cast_impl(const Source& arg) + { + // Target type must be default constructible + Target result; + + if(!try_lexical_cast_impl(arg, result)) + BOOST_LCAST_THROW_BAD_CAST(Source, Target); return result; } }; - template + template struct lexical_cast_copy { + static inline bool try_lexical_cast_impl(const Source& arg, Target& result) + { + result = arg; + return true; + } + static inline const Source& lexical_cast_impl(const Source &arg) BOOST_NOEXCEPT { return arg; @@ -2201,6 +2216,17 @@ namespace boost { template struct lexical_cast_dynamic_num { + static inline bool try_lexical_cast_impl(const Source& arg, Target& result) + { + try { + result = lexical_cast_impl(arg); + } catch (const bad_lexical_cast& e) { + return false; + } + + return true; + } + static inline Target lexical_cast_impl(const Source &arg) { typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< @@ -2224,46 +2250,63 @@ namespace boost { return caster_type::lexical_cast_impl(arg); } }; + + template + struct lexical_cast_caster_type_detector { + 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 + >::value, + boost::type_traits::ice_and< + boost::is_same::value, + boost::detail::is_character::value + >::value + > shall_we_copy_t; + + typedef boost::detail::is_arithmetic_and_not_xchars + shall_we_copy_with_dynamic_check_t; + + // We do evaluate second `if_` lazily to avoid unnecessary instantiations + // of `shall_we_copy_with_dynamic_check_t` and improve compilation times. + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< + shall_we_copy_t::value, + boost::mpl::identity >, + boost::mpl::if_< + shall_we_copy_with_dynamic_check_t, + boost::detail::lexical_cast_dynamic_num, + boost::detail::lexical_cast_do_cast + > + >::type caster_type_lazy; + + typedef BOOST_DEDUCED_TYPENAME caster_type_lazy::type caster_type; + }; } 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::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, - boost::type_traits::ice_and< - boost::is_same::value, - boost::detail::is_character::value - >::value - > shall_we_copy_t; - - typedef boost::detail::is_arithmetic_and_not_xchars - shall_we_copy_with_dynamic_check_t; - - // We do evaluate second `if_` lazily to avoid unnecessary instantiations - // of `shall_we_copy_with_dynamic_check_t` and improve compilation times. - typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< - shall_we_copy_t::value, - boost::mpl::identity >, - boost::mpl::if_< - shall_we_copy_with_dynamic_check_t, - boost::detail::lexical_cast_dynamic_num, - boost::detail::lexical_cast_do_cast - > - >::type caster_type_lazy; - - typedef BOOST_DEDUCED_TYPENAME caster_type_lazy::type caster_type; + typedef BOOST_DEDUCED_TYPENAME + boost::detail::lexical_cast_caster_type_detector + ::caster_type caster_type; return caster_type::lexical_cast_impl(arg); } + template + inline bool try_lexical_cast(const Source &arg, Target& result) + { + typedef BOOST_DEDUCED_TYPENAME + boost::detail::lexical_cast_caster_type_detector + ::caster_type caster_type; + + return caster_type::try_lexical_cast_impl(arg, result); + } + template inline Target lexical_cast(const char* chars, std::size_t count) { @@ -2272,6 +2315,13 @@ namespace boost { ); } + template + inline bool try_lexical_cast(const char* chars, std::size_t count, Target& result) + { + return ::boost::try_lexical_cast( + ::boost::iterator_range(chars, chars + count), result + ); + } template inline Target lexical_cast(const unsigned char* chars, std::size_t count) @@ -2281,6 +2331,14 @@ namespace boost { ); } + template + inline bool try_lexical_cast(const unsigned char* chars, std::size_t count, Target& result) + { + return ::boost::try_lexical_cast( + ::boost::iterator_range(chars, chars + count), result + ); + } + template inline Target lexical_cast(const signed char* chars, std::size_t count) { @@ -2289,6 +2347,14 @@ namespace boost { ); } + template + inline bool try_lexical_cast(const signed char* chars, std::size_t count, Target& result) + { + return ::boost::try_lexical_cast( + ::boost::iterator_range(chars, chars + count), result + ); + } + #ifndef BOOST_LCAST_NO_WCHAR_T template inline Target lexical_cast(const wchar_t* chars, std::size_t count) @@ -2297,6 +2363,14 @@ namespace boost { ::boost::iterator_range(chars, chars + count) ); } + + template + inline bool try_lexical_cast(const wchar_t* chars, std::size_t count, Target& result) + { + return ::boost::try_lexical_cast( + ::boost::iterator_range(chars, chars + count), result + ); + } #endif #ifndef BOOST_NO_CXX11_CHAR16_T template @@ -2306,6 +2380,14 @@ namespace boost { ::boost::iterator_range(chars, chars + count) ); } + + template + inline bool try_lexical_cast(const char16_t* chars, std::size_t count, Target& result) + { + return ::boost::try_lexical_cast( + ::boost::iterator_range(chars, chars + count), result + ); + } #endif #ifndef BOOST_NO_CXX11_CHAR32_T template @@ -2315,6 +2397,14 @@ namespace boost { ::boost::iterator_range(chars, chars + count) ); } + + template + inline bool try_lexical_cast(const char32_t* chars, std::size_t count, Target& result) + { + return ::boost::try_lexical_cast( + ::boost::iterator_range(chars, chars + count), result + ); + } #endif } // namespace boost