@@ -628,21 +628,33 @@ namespace po {
628
628
template <typename T, typename forward_iterator_t >
629
629
parsing_report<T> str2int (forward_iterator_t first, forward_iterator_t last) {
630
630
static_assert (std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, " str2uint only supports signed integral types" );
631
+ static_assert (std::numeric_limits<T>::min () == -std::numeric_limits<T>::max () - 1 , " type insufficient; doesn't employ two's complement" );
632
+
633
+ using unsigned_t = typename std::make_unsigned<T>::type;
634
+ static_assert (std::numeric_limits<unsigned_t >::max () > std::numeric_limits<T>::max (), " type insufficient" );
631
635
632
636
for (; first != last && std::isspace (*first); ++first);
633
637
const bool neg = expect (first, last, ' -' );
634
638
if (!neg)
635
639
expect (first, last, ' +' );
636
640
if (first == last || !is_digit (*first))
637
641
return error_code::conversion_error;
638
- using unsigned_t = typename std::make_unsigned<T>::type;
639
642
const auto report = str2uint<unsigned_t >(first, last);
640
643
if (!report)
641
644
return report.error ;
642
- unsigned_t max = neg ? static_cast <unsigned_t >(-std::numeric_limits<T>::min ()) : static_cast <unsigned_t >(std::numeric_limits<T>::max ());
643
- if (report > max)
644
- return error_code::out_of_range;
645
- return neg ? -static_cast <T>(report) : static_cast <T>(report);
645
+ if (neg) {
646
+ constexpr unsigned_t neg_max = static_cast <unsigned_t >(std::numeric_limits<T>::max ()) + 1 ;
647
+ if (report > neg_max)
648
+ return error_code::out_of_range;
649
+ else if (report == neg_max)
650
+ return std::numeric_limits<T>::min ();
651
+ else
652
+ return -static_cast <T>(report);
653
+ } else {
654
+ if (report > static_cast <unsigned_t >(std::numeric_limits<T>::max ()))
655
+ return error_code::out_of_range;
656
+ return static_cast <T>(report);
657
+ }
646
658
}
647
659
template <typename T>
648
660
parsing_report<T> str2int (std::string const & str) {
0 commit comments