Skip to content

Commit

Permalink
Do not use custom traits from input/output types as it leads to linkt…
Browse files Browse the repository at this point in the history
…ime or runtime errors (fixes #46) (#74)
  • Loading branch information
apolukhin authored Feb 15, 2024
1 parent 3433c34 commit 02e5821
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 68 deletions.
7 changes: 5 additions & 2 deletions doc/lexical_cast.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,13 @@ limitation of compiler options that you use.

* Significant rewrite of the internal logic to separate optimized and C++ Standard Library IO-based streams:
* C++ Standard Library based streams now constructed in less cases leading to [*better performance];
* less template instantiations and simpler maintainance;
* less template instantiations and simpler code;
* always use `std::char_traits` (do not use custom traits from input/output types as it leads to linktime or runtime errors);
* support for `volatile` input types was dropped, following the C++ Standard Library trend.
* Optimized conversions from std::basic_string_view and boost::basic_string_view
* Dropped dependency on Boost.NumericConversion and Boost.MPL
* Dropped dependency on Boost.NumericConversion and Boost.MPL. Fixed some cases
of converting floting point types to arithmetics.
* The library now works fine with `-fno-sanitize-recover=integer`.

* [*boost 1.84.0 :]

Expand Down
47 changes: 1 addition & 46 deletions include/boost/lexical_cast/detail/converter_lexical.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,47 +322,6 @@ namespace boost {
};
}

namespace detail // extract_char_traits template
{
// We are attempting to get char_traits<> from T
// template parameter. Otherwise we'll be using std::char_traits<Char>
template < class Char, class T >
struct extract_char_traits
: boost::false_type
{
typedef std::char_traits< Char > trait_t;
};

template < class Char, class Traits, class Alloc >
struct extract_char_traits< Char, std::basic_string< Char, Traits, Alloc > >
: boost::true_type
{
typedef Traits trait_t;
};

template < class Char, class Traits, class Alloc>
struct extract_char_traits< Char, boost::container::basic_string< Char, Traits, Alloc > >
: boost::true_type
{
typedef Traits trait_t;
};

#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
template < class Char, class Traits >
struct extract_char_traits< Char, std::basic_string_view< Char, Traits > >
: boost::true_type
{
typedef Traits trait_t;
};
#endif
template < class Char, class Traits >
struct extract_char_traits< Char, boost::basic_string_view< Char, Traits > >
: boost::true_type
{
typedef Traits trait_t;
};
}

namespace detail // array_to_pointer_decay<T>
{
template<class T>
Expand Down Expand Up @@ -466,11 +425,7 @@ namespace boost {
"Your compiler does not have full support for char32_t" );
#endif

typedef typename boost::conditional<
boost::detail::extract_char_traits<char_type, Target>::value,
typename boost::detail::extract_char_traits<char_type, Target>,
typename boost::detail::extract_char_traits<char_type, no_cv_src>
>::type::trait_t traits;
typedef std::char_traits<char_type> traits;

typedef boost::detail::lcast_src_length<no_cv_src> len_t;
};
Expand Down
24 changes: 12 additions & 12 deletions include/boost/lexical_cast/detail/converter_lexical_streams.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,15 @@ namespace boost { namespace detail { namespace lcast {
), bool
>::type;

template<class Alloc>
bool stream_in(lcast::exact<std::basic_string<CharT,Traits,Alloc>> x) noexcept {
template<class CharTraits, class Alloc>
bool stream_in(lcast::exact<std::basic_string<CharT,CharTraits,Alloc>> x) noexcept {
start = x.payload.data();
finish = start + x.payload.length();
return true;
}

template<class Alloc>
bool stream_in(lcast::exact<boost::container::basic_string<CharT,Traits,Alloc>> x) noexcept {
template<class CharTraits, class Alloc>
bool stream_in(lcast::exact<boost::container::basic_string<CharT,CharTraits,Alloc>> x) noexcept {
start = x.payload.data();
finish = start + x.payload.length();
return true;
Expand Down Expand Up @@ -342,15 +342,15 @@ namespace boost { namespace detail { namespace lcast {
}

#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
template <class C>
template <class C, class CharTraits>
enable_if_compatible_char_t<C>
stream_in(lcast::exact<std::basic_string_view<C, Traits>> x) noexcept {
stream_in(lcast::exact<std::basic_string_view<C, CharTraits>> x) noexcept {
return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), x.payload.size());
}
#endif
template <class C>
template <class C, class CharTraits>
enable_if_compatible_char_t<C>
stream_in(lcast::exact<boost::basic_string_view<C, Traits>> x) noexcept {
stream_in(lcast::exact<boost::basic_string_view<C, CharTraits>> x) noexcept {
return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), x.payload.size());
}
};
Expand Down Expand Up @@ -648,13 +648,13 @@ namespace boost { namespace detail { namespace lcast {
#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
bool stream_out(char32_t& output) { return shr_xchar(output); }
#endif
template<class Alloc>
bool stream_out(std::basic_string<CharT,Traits,Alloc>& str) {
template<class CharTraits, class Alloc>
bool stream_out(std::basic_string<CharT,CharTraits,Alloc>& str) {
str.assign(start, finish); return true;
}

template<class Alloc>
bool stream_out(boost::container::basic_string<CharT,Traits,Alloc>& str) {
template<class CharTraits, class Alloc>
bool stream_out(boost::container::basic_string<CharT,CharTraits,Alloc>& str) {
str.assign(start, finish); return true;
}

Expand Down
14 changes: 6 additions & 8 deletions test/lexical_cast_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,6 @@ void test_no_whitespace_stripping()
BOOST_TEST_THROWS(lexical_cast<int>("123 "), bad_lexical_cast);
}

#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
void test_traits()
{
typedef std::basic_string<char, my_traits<char> > my_string;
Expand All @@ -399,6 +398,8 @@ void test_traits()
BOOST_TEST(boost::lexical_cast<char>(s) == s[0]);
BOOST_TEST(boost::lexical_cast<my_string>(s) == s);
BOOST_TEST(boost::lexical_cast<my_string>(-1) == "-1");
BOOST_TEST(boost::lexical_cast<int>(my_string("42")) == 42);
BOOST_TEST(boost::lexical_cast<double>(my_string("1.0")) == 1.0);
}

void test_wtraits()
Expand All @@ -408,9 +409,9 @@ void test_wtraits()
my_string const s(L"s");
BOOST_TEST(boost::lexical_cast<wchar_t>(s) == s[0]);
BOOST_TEST(boost::lexical_cast<my_string>(s) == s);
//BOOST_TEST(boost::lexical_cast<my_string>(-1) == L"-1");
// Commented out because gcc 3.3 doesn't support this:
// basic_ostream<wchar_t, my_traits<wchar_t> > o; o << -1;
BOOST_TEST(boost::lexical_cast<my_string>(-1) == L"-1");
BOOST_TEST(boost::lexical_cast<int>(my_string(L"42")) == 42);
BOOST_TEST(boost::lexical_cast<double>(my_string(L"1.0")) == 1.0);
}

void test_allocator()
Expand Down Expand Up @@ -457,8 +458,6 @@ void test_wallocator()
#endif
}

#endif


void test_char_types_conversions()
{
Expand Down Expand Up @@ -578,12 +577,11 @@ int main()
#endif
test_bad_lexical_cast();
test_no_whitespace_stripping();
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION

test_traits();
test_wtraits();
test_allocator();
test_wallocator();
#endif

test_char_types_conversions();
operators_overload_test();
Expand Down

0 comments on commit 02e5821

Please sign in to comment.