Skip to content

Commit 02e5821

Browse files
authored
Do not use custom traits from input/output types as it leads to linktime or runtime errors (fixes #46) (#74)
1 parent 3433c34 commit 02e5821

File tree

4 files changed

+24
-68
lines changed

4 files changed

+24
-68
lines changed

doc/lexical_cast.qbk

+5-2
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,13 @@ limitation of compiler options that you use.
239239

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

247250
* [*boost 1.84.0 :]
248251

include/boost/lexical_cast/detail/converter_lexical.hpp

+1-46
Original file line numberDiff line numberDiff line change
@@ -322,47 +322,6 @@ namespace boost {
322322
};
323323
}
324324

325-
namespace detail // extract_char_traits template
326-
{
327-
// We are attempting to get char_traits<> from T
328-
// template parameter. Otherwise we'll be using std::char_traits<Char>
329-
template < class Char, class T >
330-
struct extract_char_traits
331-
: boost::false_type
332-
{
333-
typedef std::char_traits< Char > trait_t;
334-
};
335-
336-
template < class Char, class Traits, class Alloc >
337-
struct extract_char_traits< Char, std::basic_string< Char, Traits, Alloc > >
338-
: boost::true_type
339-
{
340-
typedef Traits trait_t;
341-
};
342-
343-
template < class Char, class Traits, class Alloc>
344-
struct extract_char_traits< Char, boost::container::basic_string< Char, Traits, Alloc > >
345-
: boost::true_type
346-
{
347-
typedef Traits trait_t;
348-
};
349-
350-
#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
351-
template < class Char, class Traits >
352-
struct extract_char_traits< Char, std::basic_string_view< Char, Traits > >
353-
: boost::true_type
354-
{
355-
typedef Traits trait_t;
356-
};
357-
#endif
358-
template < class Char, class Traits >
359-
struct extract_char_traits< Char, boost::basic_string_view< Char, Traits > >
360-
: boost::true_type
361-
{
362-
typedef Traits trait_t;
363-
};
364-
}
365-
366325
namespace detail // array_to_pointer_decay<T>
367326
{
368327
template<class T>
@@ -466,11 +425,7 @@ namespace boost {
466425
"Your compiler does not have full support for char32_t" );
467426
#endif
468427

469-
typedef typename boost::conditional<
470-
boost::detail::extract_char_traits<char_type, Target>::value,
471-
typename boost::detail::extract_char_traits<char_type, Target>,
472-
typename boost::detail::extract_char_traits<char_type, no_cv_src>
473-
>::type::trait_t traits;
428+
typedef std::char_traits<char_type> traits;
474429

475430
typedef boost::detail::lcast_src_length<no_cv_src> len_t;
476431
};

include/boost/lexical_cast/detail/converter_lexical_streams.hpp

+12-12
Original file line numberDiff line numberDiff line change
@@ -264,15 +264,15 @@ namespace boost { namespace detail { namespace lcast {
264264
), bool
265265
>::type;
266266

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

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

344344
#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
345-
template <class C>
345+
template <class C, class CharTraits>
346346
enable_if_compatible_char_t<C>
347-
stream_in(lcast::exact<std::basic_string_view<C, Traits>> x) noexcept {
347+
stream_in(lcast::exact<std::basic_string_view<C, CharTraits>> x) noexcept {
348348
return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), x.payload.size());
349349
}
350350
#endif
351-
template <class C>
351+
template <class C, class CharTraits>
352352
enable_if_compatible_char_t<C>
353-
stream_in(lcast::exact<boost::basic_string_view<C, Traits>> x) noexcept {
353+
stream_in(lcast::exact<boost::basic_string_view<C, CharTraits>> x) noexcept {
354354
return shl_char_array_limited(reinterpret_cast<const CharT*>(x.payload.data()), x.payload.size());
355355
}
356356
};
@@ -648,13 +648,13 @@ namespace boost { namespace detail { namespace lcast {
648648
#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
649649
bool stream_out(char32_t& output) { return shr_xchar(output); }
650650
#endif
651-
template<class Alloc>
652-
bool stream_out(std::basic_string<CharT,Traits,Alloc>& str) {
651+
template<class CharTraits, class Alloc>
652+
bool stream_out(std::basic_string<CharT,CharTraits,Alloc>& str) {
653653
str.assign(start, finish); return true;
654654
}
655655

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

test/lexical_cast_test.cpp

+6-8
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,6 @@ void test_no_whitespace_stripping()
390390
BOOST_TEST_THROWS(lexical_cast<int>("123 "), bad_lexical_cast);
391391
}
392392

393-
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
394393
void test_traits()
395394
{
396395
typedef std::basic_string<char, my_traits<char> > my_string;
@@ -399,6 +398,8 @@ void test_traits()
399398
BOOST_TEST(boost::lexical_cast<char>(s) == s[0]);
400399
BOOST_TEST(boost::lexical_cast<my_string>(s) == s);
401400
BOOST_TEST(boost::lexical_cast<my_string>(-1) == "-1");
401+
BOOST_TEST(boost::lexical_cast<int>(my_string("42")) == 42);
402+
BOOST_TEST(boost::lexical_cast<double>(my_string("1.0")) == 1.0);
402403
}
403404

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

416417
void test_allocator()
@@ -457,8 +458,6 @@ void test_wallocator()
457458
#endif
458459
}
459460

460-
#endif
461-
462461

463462
void test_char_types_conversions()
464463
{
@@ -578,12 +577,11 @@ int main()
578577
#endif
579578
test_bad_lexical_cast();
580579
test_no_whitespace_stripping();
581-
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
580+
582581
test_traits();
583582
test_wtraits();
584583
test_allocator();
585584
test_wallocator();
586-
#endif
587585

588586
test_char_types_conversions();
589587
operators_overload_test();

0 commit comments

Comments
 (0)