mirror of
https://github.com/boostorg/conversion.git
synced 2025-08-03 22:44:32 +02:00
Added some tests for try_lexical_convert and fixed some issues.
This commit is contained in:
@@ -1394,14 +1394,7 @@ namespace boost {
|
||||
}
|
||||
|
||||
template<typename InputStreamable>
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
bool shl_input_streamable(InputStreamable&& input) {
|
||||
typedef InputStreamable&& forward_type;
|
||||
#else
|
||||
bool shl_input_streamable(InputStreamable& input) {
|
||||
typedef InputStreamable& forward_type;
|
||||
#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
|
||||
// If you have compilation error at this point, than your STL library
|
||||
// does not support such conversions. Try updating it.
|
||||
@@ -1412,7 +1405,7 @@ namespace boost {
|
||||
out_stream.exceptions(std::ios::badbit);
|
||||
try {
|
||||
#endif
|
||||
bool const result = !(out_stream << static_cast<forward_type>(input)).fail();
|
||||
bool const result = !(out_stream << input).fail();
|
||||
const buffer_t* const p = static_cast<buffer_t*>(
|
||||
static_cast<std::basic_streambuf<CharT, Traits>*>(out_stream.rdbuf())
|
||||
);
|
||||
@@ -1673,7 +1666,6 @@ namespace boost {
|
||||
return ((*this) << reinterpret_cast<boost::array<C, N> const& >(input));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class InStreamable>
|
||||
bool operator<<(const InStreamable& input) { return shl_input_streamable(input); }
|
||||
};
|
||||
@@ -2081,21 +2073,14 @@ namespace boost {
|
||||
BOOST_DEDUCED_TYPENAME stream_trait::traits
|
||||
> o_interpreter_type;
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <class T>
|
||||
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.
|
||||
//
|
||||
// For compilers with perfect forwarding `static_cast<forward_type>(arg)` is
|
||||
// eqaul to `std::forward<T>(arg)`.
|
||||
if (!(i_interpreter.operator <<(static_cast<forward_type>(arg))))
|
||||
if (!(i_interpreter.operator <<(arg)))
|
||||
return false;
|
||||
|
||||
o_interpreter_type out(i_interpreter.cbegin(), i_interpreter.cend());
|
||||
@@ -2263,56 +2248,76 @@ namespace boost {
|
||||
};
|
||||
}
|
||||
|
||||
namespace conversion { namespace detail {
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
template <typename Target, typename Source>
|
||||
inline bool try_lexical_convert(Source&& arg, Target& result)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<
|
||||
BOOST_DEDUCED_TYPENAME boost::remove_reference<Source>::type
|
||||
>::type no_cr_source_t;
|
||||
template <typename Target, typename Source>
|
||||
inline bool try_lexical_convert(Source&& arg, Target& result)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::remove_const<
|
||||
BOOST_DEDUCED_TYPENAME boost::remove_reference<Source>::type
|
||||
>::type no_cr_source_t;
|
||||
|
||||
typedef Source&& forward_type;
|
||||
typedef Source&& forward_type;
|
||||
#else
|
||||
template <typename Target, typename Source>
|
||||
inline bool try_lexical_convert(const Source& arg, Target& result)
|
||||
{
|
||||
typedef Source no_cr_source_t;
|
||||
typedef const Source& forward_type;
|
||||
template <typename Target, typename Source>
|
||||
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<no_cr_source_t>::type src;
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay<no_cr_source_t>::type src;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::type_traits::ice_or<
|
||||
boost::detail::is_xchar_to_xchar<Target, src >::value,
|
||||
boost::detail::is_char_array_to_stdstring<Target, src >::value,
|
||||
boost::type_traits::ice_and<
|
||||
boost::is_same<Target, src >::value,
|
||||
boost::detail::is_stdstring<Target >::value
|
||||
>::value,
|
||||
boost::type_traits::ice_and<
|
||||
boost::is_same<Target, src >::value,
|
||||
boost::detail::is_character<Target >::value
|
||||
>::value
|
||||
> shall_we_copy_t;
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::type_traits::ice_or<
|
||||
boost::detail::is_xchar_to_xchar<Target, src >::value,
|
||||
boost::detail::is_char_array_to_stdstring<Target, src >::value,
|
||||
boost::type_traits::ice_and<
|
||||
boost::is_same<Target, src >::value,
|
||||
boost::detail::is_stdstring<Target >::value
|
||||
>::value,
|
||||
boost::type_traits::ice_and<
|
||||
boost::is_same<Target, src >::value,
|
||||
boost::detail::is_character<Target >::value
|
||||
>::value
|
||||
> shall_we_copy_t;
|
||||
|
||||
typedef boost::detail::is_arithmetic_and_not_xchars<Target, src >
|
||||
shall_we_copy_with_dynamic_check_t;
|
||||
typedef boost::detail::is_arithmetic_and_not_xchars<Target, src >
|
||||
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::detail::copy_converter_impl<Target, src > >,
|
||||
boost::mpl::if_<
|
||||
shall_we_copy_with_dynamic_check_t,
|
||||
boost::detail::dynamic_num_converter_impl<Target, src >,
|
||||
boost::detail::lexical_converter_impl<Target, src >
|
||||
>
|
||||
>::type caster_type_lazy;
|
||||
// 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::detail::copy_converter_impl<Target, src > >,
|
||||
boost::mpl::if_<
|
||||
shall_we_copy_with_dynamic_check_t,
|
||||
boost::detail::dynamic_num_converter_impl<Target, src >,
|
||||
boost::detail::lexical_converter_impl<Target, src >
|
||||
>
|
||||
>::type caster_type_lazy;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME caster_type_lazy::type caster_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME caster_type_lazy::type caster_type;
|
||||
|
||||
return caster_type::try_convert(static_cast<forward_type>(arg), result);
|
||||
return caster_type::try_convert(static_cast<forward_type>(arg), result);
|
||||
}
|
||||
|
||||
template <typename Target, typename CharacterT>
|
||||
inline bool try_lexical_convert(const CharacterT* chars, std::size_t count, Target& result)
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::detail::is_character<CharacterT>::value,
|
||||
"This overload of try_lexical_convert is meant to be used only with arrays of characters."
|
||||
);
|
||||
return ::boost::conversion::detail::try_lexical_convert(
|
||||
::boost::iterator_range<const CharacterT*>(chars, chars + count), result
|
||||
);
|
||||
}
|
||||
|
||||
}} // namespace conversion::detail
|
||||
|
||||
namespace conversion {
|
||||
// ADL barrier
|
||||
using ::boost::conversion::detail::try_lexical_convert;
|
||||
}
|
||||
|
||||
template <typename Target, typename Source>
|
||||
@@ -2320,7 +2325,7 @@ namespace boost {
|
||||
{
|
||||
Target result;
|
||||
|
||||
if (!try_lexical_convert(arg, result))
|
||||
if (!boost::conversion::detail::try_lexical_convert(arg, result))
|
||||
BOOST_LCAST_THROW_BAD_CAST(Source, Target);
|
||||
|
||||
return result;
|
||||
@@ -2334,27 +2339,11 @@ namespace boost {
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Target>
|
||||
inline bool try_lexical_convert(const char* chars, std::size_t count, Target& result)
|
||||
{
|
||||
return ::boost::try_lexical_convert(
|
||||
::boost::iterator_range<const char*>(chars, chars + count), result
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Target>
|
||||
inline Target lexical_cast(const unsigned char* chars, std::size_t count)
|
||||
{
|
||||
return ::boost::lexical_cast<Target>(
|
||||
return ::boost::lexical_cast<Target>(
|
||||
::boost::iterator_range<const unsigned char*>(chars, chars + count)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Target>
|
||||
inline bool try_lexical_convert(const unsigned char* chars, std::size_t count, Target& result)
|
||||
{
|
||||
return ::boost::try_lexical_convert(
|
||||
::boost::iterator_range<const unsigned char*>(chars, chars + count), result
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2366,14 +2355,6 @@ namespace boost {
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Target>
|
||||
inline bool try_lexical_convert(const signed char* chars, std::size_t count, Target& result)
|
||||
{
|
||||
return ::boost::try_lexical_convert(
|
||||
::boost::iterator_range<const signed char*>(chars, chars + count), result
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
template <typename Target>
|
||||
inline Target lexical_cast(const wchar_t* chars, std::size_t count)
|
||||
@@ -2382,14 +2363,6 @@ namespace boost {
|
||||
::boost::iterator_range<const wchar_t*>(chars, chars + count)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Target>
|
||||
inline bool try_lexical_convert(const wchar_t* chars, std::size_t count, Target& result)
|
||||
{
|
||||
return ::boost::try_lexical_convert(
|
||||
::boost::iterator_range<const wchar_t*>(chars, chars + count), result
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
template <typename Target>
|
||||
@@ -2399,14 +2372,6 @@ namespace boost {
|
||||
::boost::iterator_range<const char16_t*>(chars, chars + count)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Target>
|
||||
inline bool try_lexical_convert(const char16_t* chars, std::size_t count, Target& result)
|
||||
{
|
||||
return ::boost::try_lexical_convert(
|
||||
::boost::iterator_range<const char16_t*>(chars, chars + count), result
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
template <typename Target>
|
||||
@@ -2416,14 +2381,6 @@ namespace boost {
|
||||
::boost::iterator_range<const char32_t*>(chars, chars + count)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Target>
|
||||
inline bool try_lexical_convert(const char32_t* chars, std::size_t count, Target& result)
|
||||
{
|
||||
return ::boost::try_lexical_convert(
|
||||
::boost::iterator_range<const char32_t*>(chars, chars + count), result
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
@@ -62,6 +62,7 @@ test-suite conversion
|
||||
[ run lexical_cast_stream_traits_test.cpp ]
|
||||
[ compile-fail lexical_cast_to_pointer_test.cpp ]
|
||||
[ run lexical_cast_filesystem_test.cpp ../../filesystem/build//boost_filesystem/<link>static ]
|
||||
[ run lexical_cast_try_lexical_convert.cpp ]
|
||||
;
|
||||
|
||||
# Assuring that examples compile and run. Adding sources from `example` directory to the `conversion` test suite.
|
||||
|
78
test/lexical_cast_try_lexical_convert.cpp
Normal file
78
test/lexical_cast_try_lexical_convert.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// Unit test for boost::lexical_cast.
|
||||
//
|
||||
// See http://www.boost.org for most recent version, including documentation.
|
||||
//
|
||||
// Copyright Antony Polukhin, 2014.
|
||||
//
|
||||
// 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 <boost/config.hpp>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void try_uncommon_cases()
|
||||
{
|
||||
std::string sres;
|
||||
const bool res1 = conversion::try_lexical_convert(std::string("Test string"), sres);
|
||||
BOOST_CHECK(res1);
|
||||
BOOST_CHECK_EQUAL(sres, "Test string");
|
||||
|
||||
volatile int vires;
|
||||
const bool res2 = conversion::try_lexical_convert(100, vires);
|
||||
BOOST_CHECK(res2);
|
||||
BOOST_CHECK_EQUAL(vires, 100);
|
||||
|
||||
const bool res3 = conversion::try_lexical_convert("Test string", sres);
|
||||
BOOST_CHECK(res3);
|
||||
BOOST_CHECK_EQUAL(sres, "Test string");
|
||||
|
||||
const bool res4 = conversion::try_lexical_convert("Test string", sizeof("Test string") - 1, sres);
|
||||
BOOST_CHECK(res4);
|
||||
BOOST_CHECK_EQUAL(sres, "Test string");
|
||||
|
||||
int ires;
|
||||
BOOST_CHECK(!conversion::try_lexical_convert("Test string", ires));
|
||||
BOOST_CHECK(!conversion::try_lexical_convert(1.1, ires));
|
||||
BOOST_CHECK(!conversion::try_lexical_convert(-1.9, ires));
|
||||
BOOST_CHECK(!conversion::try_lexical_convert("1.1", ires));
|
||||
BOOST_CHECK(!conversion::try_lexical_convert("1000000000000000000000000000000000000000", ires));
|
||||
}
|
||||
|
||||
|
||||
void try_common_cases()
|
||||
{
|
||||
int ires = 0;
|
||||
const bool res1 = conversion::try_lexical_convert(std::string("100"), ires);
|
||||
BOOST_CHECK(res1);
|
||||
BOOST_CHECK_EQUAL(ires, 100);
|
||||
|
||||
ires = 0;
|
||||
const bool res2 = conversion::try_lexical_convert("-100", ires);
|
||||
BOOST_CHECK(res2);
|
||||
BOOST_CHECK_EQUAL(ires, -100);
|
||||
|
||||
float fres = 1.0f;
|
||||
const bool res3 = conversion::try_lexical_convert("0.0", fres);
|
||||
BOOST_CHECK(res3);
|
||||
BOOST_CHECK_EQUAL(fres, 0.0f);
|
||||
|
||||
fres = 1.0f;
|
||||
const bool res4 = conversion::try_lexical_convert("0.0", sizeof("0.0") - 1, fres);
|
||||
BOOST_CHECK(res4);
|
||||
BOOST_CHECK_EQUAL(fres, 0.0f);
|
||||
}
|
||||
|
||||
unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||
{
|
||||
unit_test::test_suite *suite =
|
||||
BOOST_TEST_SUITE("Tests for try_lexical_convert");
|
||||
suite->add(BOOST_TEST_CASE(&try_uncommon_cases));
|
||||
suite->add(BOOST_TEST_CASE(&try_common_cases));
|
||||
|
||||
return suite;
|
||||
}
|
Reference in New Issue
Block a user