Chris@102: // Copyright Kevlin Henney, 2000-2005. Chris@102: // Copyright Alexander Nasonov, 2006-2010. Chris@102: // Copyright Antony Polukhin, 2011-2014. Chris@102: // Chris@102: // Distributed under the Boost Software License, Version 1.0. (See Chris@102: // accompanying file LICENSE_1_0.txt or copy at Chris@102: // http://www.boost.org/LICENSE_1_0.txt) Chris@102: // Chris@102: // what: lexical_cast custom keyword cast Chris@102: // who: contributed by Kevlin Henney, Chris@102: // enhanced with contributions from Terje Slettebo, Chris@102: // with additional fixes and suggestions from Gennaro Prota, Chris@102: // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, Chris@102: // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, Chris@102: // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters Chris@102: // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 Chris@102: Chris@102: #ifndef BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP Chris@102: #define BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP Chris@102: Chris@102: #include Chris@102: #ifdef BOOST_HAS_PRAGMA_ONCE Chris@102: # pragma once Chris@102: #endif Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: #include Chris@102: #include Chris@102: #include Chris@102: Chris@102: #include Chris@102: #include Chris@102: Chris@102: namespace boost { Chris@102: namespace detail Chris@102: { Chris@102: template Chris@102: struct is_stdstring Chris@102: : boost::false_type Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct is_stdstring< std::basic_string > Chris@102: : boost::true_type Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct is_stdstring< boost::container::basic_string > Chris@102: : boost::true_type Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct is_arithmetic_and_not_xchars Chris@102: { Chris@102: BOOST_STATIC_CONSTANT(bool, value = ( Chris@102: boost::type_traits::ice_and< Chris@102: boost::type_traits::ice_not< Chris@102: boost::detail::is_character::value Chris@102: >::value, Chris@102: boost::type_traits::ice_not< Chris@102: boost::detail::is_character::value Chris@102: >::value, Chris@102: boost::is_arithmetic::value, Chris@102: boost::is_arithmetic::value Chris@102: >::value Chris@102: )); Chris@102: }; Chris@102: Chris@102: /* Chris@102: * is_xchar_to_xchar::value is true, Chris@102: * Target and Souce are char types of the same size 1 (char, signed char, unsigned char). Chris@102: */ Chris@102: template Chris@102: struct is_xchar_to_xchar Chris@102: { Chris@102: BOOST_STATIC_CONSTANT(bool, value = ( Chris@102: boost::type_traits::ice_and< Chris@102: boost::type_traits::ice_eq::value, Chris@102: boost::type_traits::ice_eq::value, Chris@102: boost::detail::is_character::value, Chris@102: boost::detail::is_character::value Chris@102: >::value Chris@102: )); Chris@102: }; Chris@102: Chris@102: template Chris@102: struct is_char_array_to_stdstring Chris@102: : boost::false_type Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct is_char_array_to_stdstring< std::basic_string, CharT* > Chris@102: : boost::true_type Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct is_char_array_to_stdstring< std::basic_string, const CharT* > Chris@102: : boost::true_type Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct is_char_array_to_stdstring< boost::container::basic_string, CharT* > Chris@102: : boost::true_type Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct is_char_array_to_stdstring< boost::container::basic_string, const CharT* > Chris@102: : boost::true_type Chris@102: {}; Chris@102: Chris@102: template Chris@102: struct copy_converter_impl Chris@102: { Chris@102: // MSVC fail to forward an array (DevDiv#555157 "SILENT BAD CODEGEN triggered by perfect forwarding", Chris@102: // fixed in 2013 RTM). Chris@102: #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined(BOOST_MSVC) || BOOST_MSVC >= 1800) Chris@102: template Chris@102: static inline bool try_convert(T&& arg, Target& result) { Chris@102: result = static_cast(arg); // eqaul to `result = std::forward(arg);` Chris@102: return true; Chris@102: } Chris@102: #else Chris@102: static inline bool try_convert(const Source& arg, Target& result) { Chris@102: result = arg; Chris@102: return true; Chris@102: } Chris@102: #endif Chris@102: }; Chris@102: } Chris@102: Chris@102: namespace conversion { namespace detail { Chris@102: Chris@102: template Chris@102: inline bool try_lexical_convert(const Source& arg, Target& result) Chris@102: { Chris@102: typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay::type src; Chris@102: Chris@102: typedef BOOST_DEDUCED_TYPENAME boost::type_traits::ice_or< Chris@102: boost::detail::is_xchar_to_xchar::value, Chris@102: boost::detail::is_char_array_to_stdstring::value, Chris@102: boost::type_traits::ice_and< Chris@102: boost::is_same::value, Chris@102: boost::detail::is_stdstring::value Chris@102: >::value, Chris@102: boost::type_traits::ice_and< Chris@102: boost::is_same::value, Chris@102: boost::detail::is_character::value Chris@102: >::value Chris@102: > shall_we_copy_t; Chris@102: Chris@102: typedef boost::detail::is_arithmetic_and_not_xchars Chris@102: shall_we_copy_with_dynamic_check_t; Chris@102: Chris@102: // We do evaluate second `if_` lazily to avoid unnecessary instantiations Chris@102: // of `shall_we_copy_with_dynamic_check_t` and improve compilation times. Chris@102: typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c< Chris@102: shall_we_copy_t::value, Chris@102: boost::mpl::identity >, Chris@102: boost::mpl::if_< Chris@102: shall_we_copy_with_dynamic_check_t, Chris@102: boost::detail::dynamic_num_converter_impl, Chris@102: boost::detail::lexical_converter_impl Chris@102: > Chris@102: >::type caster_type_lazy; Chris@102: Chris@102: typedef BOOST_DEDUCED_TYPENAME caster_type_lazy::type caster_type; Chris@102: Chris@102: return caster_type::try_convert(arg, result); Chris@102: } Chris@102: Chris@102: template Chris@102: inline bool try_lexical_convert(const CharacterT* chars, std::size_t count, Target& result) Chris@102: { Chris@102: BOOST_STATIC_ASSERT_MSG( Chris@102: boost::detail::is_character::value, Chris@102: "This overload of try_lexical_convert is meant to be used only with arrays of characters." Chris@102: ); Chris@102: return ::boost::conversion::detail::try_lexical_convert( Chris@102: ::boost::iterator_range(chars, chars + count), result Chris@102: ); Chris@102: } Chris@102: Chris@102: }} // namespace conversion::detail Chris@102: Chris@102: namespace conversion { Chris@102: // ADL barrier Chris@102: using ::boost::conversion::detail::try_lexical_convert; Chris@102: } Chris@102: Chris@102: } // namespace boost Chris@102: Chris@102: #endif // BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP Chris@102: