diff --git a/include/boost/spirit/home/x3/numeric/int.hpp b/include/boost/spirit/home/x3/numeric/int.hpp index caa2739464..0202a5855e 100644 --- a/include/boost/spirit/home/x3/numeric/int.hpp +++ b/include/boost/spirit/home/x3/numeric/int.hpp @@ -1,62 +1,82 @@ /*============================================================================= Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2025 Nana Sakisaka 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) ==============================================================================*/ -#if !defined(BOOST_SPIRIT_X3_INT_APR_17_2006_0830AM) +#ifndef BOOST_SPIRIT_X3_INT_APR_17_2006_0830AM #define BOOST_SPIRIT_X3_INT_APR_17_2006_0830AM #include #include #include + +#include #include -namespace boost { namespace spirit { namespace x3 +namespace boost::spirit::x3 { - /////////////////////////////////////////////////////////////////////////// template < - typename T - , unsigned Radix = 10 - , unsigned MinDigits = 1 - , int MaxDigits = -1> + typename T, + unsigned Radix = 10, + unsigned MinDigits = 1, + int MaxDigits = -1 + > struct int_parser : parser> { // check template parameter 'Radix' for validity static_assert( (Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16), - "Error Unsupported Radix"); + "Unsupported Radix" + ); - typedef T attribute_type; - static bool const has_attribute = true; + using attribute_type = T; + static constexpr bool has_attribute = true; - template - bool parse(Iterator& first, Iterator const& last - , Context const& context, unused_type, Attribute& attr) const + template Se, typename Context, typename Attribute> + [[nodiscard]] constexpr bool parse( + It& first, Se const& last, + Context const& context, unused_type, Attribute& attr + ) const noexcept( + noexcept(x3::skip_over(first, last, context)) && + noexcept(extract_int::call(first, last, attr)) + ) { - typedef extract_int extract; x3::skip_over(first, last, context); - return extract::call(first, last, attr); + return extract_int::call(first, last, attr); } }; -#define BOOST_SPIRIT_X3_INT_PARSER(int_type, name) \ - typedef int_parser name##type; \ - constexpr name##type name = {}; \ - /***/ + inline namespace cpos + { + using short_type = int_parser; + inline constexpr short_type short_{}; + + using int_type = int_parser; + inline constexpr int_type int_{}; + + using long_type = int_parser; + inline constexpr long_type long_{}; + + using long_long_type = int_parser; + inline constexpr long_long_type long_long{}; + + + using int8_type = int_parser; + inline constexpr int8_type int8{}; + + using int16_type = int_parser; + inline constexpr int16_type int16{}; - BOOST_SPIRIT_X3_INT_PARSER(long, long_) - BOOST_SPIRIT_X3_INT_PARSER(short, short_) - BOOST_SPIRIT_X3_INT_PARSER(int, int_) - BOOST_SPIRIT_X3_INT_PARSER(long long, long_long) + using int32_type = int_parser; + inline constexpr int32_type int32{}; - BOOST_SPIRIT_X3_INT_PARSER(int8_t, int8) - BOOST_SPIRIT_X3_INT_PARSER(int16_t, int16) - BOOST_SPIRIT_X3_INT_PARSER(int32_t, int32) - BOOST_SPIRIT_X3_INT_PARSER(int64_t, int64) + using int64_type = int_parser; + inline constexpr int64_type int64{}; -#undef BOOST_SPIRIT_X3_INT_PARSER + } // cpos -}}} +} // boost::spirit::x3 #endif diff --git a/include/boost/spirit/home/x3/numeric/real.hpp b/include/boost/spirit/home/x3/numeric/real.hpp index dac46bb090..232f526937 100644 --- a/include/boost/spirit/home/x3/numeric/real.hpp +++ b/include/boost/spirit/home/x3/numeric/real.hpp @@ -1,10 +1,11 @@ /*============================================================================= Copyright (c) 2001-2014 Joel de Guzman + Copyright (c) 2025 Nana Sakisaka 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) ==============================================================================*/ -#if !defined(BOOST_SPIRIT_X3_REAL_APRIL_18_2006_0850AM) +#ifndef BOOST_SPIRIT_X3_REAL_APRIL_18_2006_0850AM #define BOOST_SPIRIT_X3_REAL_APRIL_18_2006_0850AM #include @@ -12,54 +13,80 @@ #include #include -namespace boost { namespace spirit { namespace x3 +#include +#include +#include + +namespace boost::spirit::x3 { - template > - struct real_parser : parser > + template > + struct real_parser : parser> { - typedef T attribute_type; - static bool const has_attribute = true; + using attribute_type = T; + using policies_type = RealPolicies; + + static constexpr bool has_attribute = true; - constexpr real_parser() - : policies() {} + constexpr real_parser() = default; - constexpr real_parser(RealPolicies const& policies) - : policies(policies) {} + template + requires + (!std::is_same_v, real_parser>) && + std::is_constructible_v + constexpr real_parser(RealPoliciesT&& policies) + noexcept(std::is_nothrow_constructible_v) + : policies_(std::forward(policies)) + {} - template - bool parse(Iterator& first, Iterator const& last - , Context const& context, unused_type, T& attr_) const + template Se, typename Context> + [[nodiscard]] constexpr bool + parse( + It& first, Se const& last, + Context const& context, unused_type, T& attr_ + ) const noexcept( + noexcept(x3::skip_over(first, last, context)) && + noexcept(extract_real::parse(first, last, attr_, policies_)) + ) { x3::skip_over(first, last, context); - return extract_real::parse(first, last, attr_, policies); + return extract_real::parse(first, last, attr_, policies_); } - template - bool parse(Iterator& first, Iterator const& last - , Context const& context, unused_type, Attribute& attr_param) const + template Se, typename Context, typename Attribute> + [[nodiscard]] constexpr bool + parse(It& first, Se const& last, + Context const& context, unused_type, Attribute& attr_param + ) const noexcept( + std::is_nothrow_default_constructible_v && + noexcept(this->parse(first, last, context, unused, std::declval())) && + noexcept(traits::move_to(std::declval(), attr_param)) + ) { // this case is called when Attribute is not T T attr_; - if (parse(first, last, context, unused, attr_)) + if (this->parse(first, last, context, unused, attr_)) { - traits::move_to(attr_, attr_param); + traits::move_to(std::move(attr_), attr_param); return true; } return false; } - RealPolicies policies; + private: + RealPolicies policies_{}; }; - typedef real_parser float_type; - constexpr float_type float_ = {}; - - typedef real_parser double_type; - constexpr double_type double_ = {}; + inline namespace cpos + { + using float_type = real_parser; + inline constexpr float_type float_{}; - typedef real_parser long_double_type; - constexpr long_double_type long_double = {}; + using double_type = real_parser; + inline constexpr double_type double_{}; -}}} + using long_double_type = real_parser; + inline constexpr long_double_type long_double{}; + } // cpos +} // boost::spirit::x3 #endif diff --git a/include/boost/spirit/home/x3/numeric/real_policies.hpp b/include/boost/spirit/home/x3/numeric/real_policies.hpp index 5d16aadd8e..e25d531749 100644 --- a/include/boost/spirit/home/x3/numeric/real_policies.hpp +++ b/include/boost/spirit/home/x3/numeric/real_policies.hpp @@ -6,69 +6,80 @@ 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) ==============================================================================*/ -#if !defined(BOOST_SPIRIT_X3_REAL_POLICIES_APRIL_17_2006_1158PM) +#ifndef BOOST_SPIRIT_X3_REAL_POLICIES_APRIL_17_2006_1158PM #define BOOST_SPIRIT_X3_REAL_POLICIES_APRIL_17_2006_1158PM #include #include #include +#include +#include namespace boost::spirit::x3 { - // Default (unsigned) real number policies + // Default (unsigned) real number policies template struct ureal_policies { // trailing dot policy suggested by Gustavo Guerra - static bool const allow_leading_dot = true; - static bool const allow_trailing_dot = true; - static bool const expect_dot = false; + static constexpr bool allow_leading_dot = true; + static constexpr bool allow_trailing_dot = true; + static constexpr bool expect_dot = false; - template - static bool - parse_sign(Iterator& /*first*/, Iterator const& /*last*/) + template Se> + [[nodiscard]] static constexpr bool + parse_sign(It& /*first*/, Se const& /*last*/) noexcept { return false; } - template - static bool - parse_n(Iterator& first, Iterator const& last, Attribute& attr_) + template Se, typename Attribute> + [[nodiscard]] static constexpr bool + parse_n(It& first, Se const& last, Attribute& attr_) + noexcept(noexcept(extract_uint::call(first, last, attr_))) { return extract_uint::call(first, last, attr_); } - template - static bool - parse_dot(Iterator& first, Iterator const& last) + template Se> + [[nodiscard]] static constexpr bool + parse_dot(It& first, Se const& last) + noexcept(noexcept(*first) && noexcept(++first)) { if (first == last || *first != '.') + { return false; + } ++first; return true; } - template - static bool - parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr_) + template Se, typename Attribute> + [[nodiscard]] static constexpr bool + parse_frac_n(It& first, Se const& last, Attribute& attr_) + noexcept(noexcept(extract_uint::call(first, last, attr_))) { return extract_uint::call(first, last, attr_); } - template - static bool - parse_exp(Iterator& first, Iterator const& last) + template Se> + [[nodiscard]] static constexpr bool + parse_exp(It& first, Se const& last) + noexcept(noexcept(*first) && noexcept(++first)) { if (first == last || (*first != 'e' && *first != 'E')) + { return false; + } ++first; return true; } - template - static bool - parse_exp_n(Iterator& first, Iterator const& last, int& attr_) + template Se> + [[nodiscard]] static constexpr bool + parse_exp_n(It& first, Se const& last, int& attr_) + noexcept(noexcept(extract_int::call(first, last, attr_))) { return extract_int::call(first, last, attr_); } @@ -85,17 +96,14 @@ namespace boost::spirit::x3 // and Inf as mandated by the C99 Standard and as proposed for // inclusion into the C++0x Standard: nan, nan(...), inf and infinity // (the matching is performed case-insensitively). - template - static bool - parse_nan(Iterator& first, Iterator const& last, Attribute& attr_) + template Se, typename Attribute> + [[nodiscard]] static constexpr bool + parse_nan(It& first, Se const& last, Attribute& attr_) { using namespace std::string_view_literals; - if (first == last) - return false; // end of input reached - - if (*first != 'n' && *first != 'N') - return false; // not "nan" + if (first == last) return false; // end of input reached + if (*first != 'n' && *first != 'N') return false; // not "nan" // nan[(...)] ? if (detail::string_parse("nan"sv, "NAN"sv, first, last, unused)) @@ -103,7 +111,7 @@ namespace boost::spirit::x3 if (first != last && *first == '(') { // skip trailing (...) part - Iterator i = first; + It i = first; while (++i != last && *i != ')') ; @@ -118,17 +126,14 @@ namespace boost::spirit::x3 return false; } - template - static bool - parse_inf(Iterator& first, Iterator const& last, Attribute& attr_) + template Se, typename Attribute> + [[nodiscard]] static constexpr bool + parse_inf(It& first, Se const& last, Attribute& attr_) { using namespace std::string_view_literals; - if (first == last) - return false; // end of input reached - - if (*first != 'i' && *first != 'I') - return false; // not "inf" + if (first == last) return false; // end of input reached + if (*first != 'i' && *first != 'I') return false; // not "inf" // inf or infinity ? if (detail::string_parse("inf"sv, "INF"sv, first, last, unused)) @@ -146,24 +151,25 @@ namespace boost::spirit::x3 template struct real_policies : ureal_policies { - template - static bool - parse_sign(Iterator& first, Iterator const& last) + template Se> + [[nodiscard]] static constexpr bool + parse_sign(It& first, Se const& last) + noexcept(noexcept(detail::extract_sign(first, last))) { - return extract_sign(first, last); + return detail::extract_sign(first, last); } }; template struct strict_ureal_policies : ureal_policies { - static bool const expect_dot = true; + static constexpr bool expect_dot = true; }; template struct strict_real_policies : real_policies { - static bool const expect_dot = true; + static constexpr bool expect_dot = true; }; } // boost::spirit::x3 diff --git a/include/boost/spirit/home/x3/numeric/uint.hpp b/include/boost/spirit/home/x3/numeric/uint.hpp index 869ee48f91..667f885bba 100644 --- a/include/boost/spirit/home/x3/numeric/uint.hpp +++ b/include/boost/spirit/home/x3/numeric/uint.hpp @@ -1,75 +1,91 @@ /*============================================================================= Copyright (c) 2001-2014 Joel de Guzman Copyright (c) 2011 Jan Frederick Eick + Copyright (c) 2025 Nana Sakisaka 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) ==============================================================================*/ -#if !defined(BOOST_SPIRIT_X3_UINT_APR_17_2006_0901AM) +#ifndef BOOST_SPIRIT_X3_UINT_APR_17_2006_0901AM #define BOOST_SPIRIT_X3_UINT_APR_17_2006_0901AM #include #include #include + +#include #include -namespace boost { namespace spirit { namespace x3 +namespace boost::spirit::x3 { - /////////////////////////////////////////////////////////////////////////// template < - typename T - , unsigned Radix = 10 - , unsigned MinDigits = 1 - , int MaxDigits = -1> + typename T, + unsigned Radix = 10, + unsigned MinDigits = 1, + int MaxDigits = -1 + > struct uint_parser : parser> { // check template parameter 'Radix' for validity - static_assert( - (Radix >= 2 && Radix <= 36), - "Error Unsupported Radix"); + static_assert((Radix >= 2 && Radix <= 36), "Unsupported Radix"); + + using attribute_type = T; - typedef T attribute_type; - static bool const has_attribute = true; + static constexpr bool has_attribute = true; - template - bool parse(Iterator& first, Iterator const& last - , Context const& context, unused_type, Attribute& attr) const + template Se, typename Context, typename Attribute> + [[nodiscard]] constexpr bool + parse( + It& first, Se const& last, + Context const& context, unused_type, Attribute& attr + ) const noexcept( + noexcept(x3::skip_over(first, last, context)) && + noexcept(extract_uint::call(first, last, attr)) + ) { - typedef extract_uint extract; x3::skip_over(first, last, context); - return extract::call(first, last, attr); + return extract_uint::call(first, last, attr); } }; -#define BOOST_SPIRIT_X3_UINT_PARSER(uint_type, name) \ - typedef uint_parser name##type; \ - constexpr name##type name = {}; \ - /***/ + inline namespace cpos + { + using ushort_type = uint_parser; + inline constexpr ushort_type ushort_{}; + + using uint_type = uint_parser; + inline constexpr uint_type uint_{}; + + using ulong_type = uint_parser; + inline constexpr ulong_type ulong_{}; + + using ulong_long_type = uint_parser; + inline constexpr ulong_long_type ulong_long{}; + + + using uint8_type = uint_parser; + inline constexpr uint8_type uint8{}; - BOOST_SPIRIT_X3_UINT_PARSER(unsigned long, ulong_) - BOOST_SPIRIT_X3_UINT_PARSER(unsigned short, ushort_) - BOOST_SPIRIT_X3_UINT_PARSER(unsigned int, uint_) - BOOST_SPIRIT_X3_UINT_PARSER(unsigned long long, ulong_long) + using uint16_type = uint_parser; + inline constexpr uint16_type uint16{}; - BOOST_SPIRIT_X3_UINT_PARSER(uint8_t, uint8) - BOOST_SPIRIT_X3_UINT_PARSER(uint16_t, uint16) - BOOST_SPIRIT_X3_UINT_PARSER(uint32_t, uint32) - BOOST_SPIRIT_X3_UINT_PARSER(uint64_t, uint64) + using uint32_type = uint_parser; + inline constexpr uint32_type uint32{}; -#undef BOOST_SPIRIT_X3_UINT_PARSER + using uint64_type = uint_parser; + inline constexpr uint64_type uint64{}; -#define BOOST_SPIRIT_X3_UINT_PARSER(uint_type, radix, name) \ - typedef uint_parser name##type; \ - constexpr name##type name = name##type(); \ - /***/ - BOOST_SPIRIT_X3_UINT_PARSER(unsigned, 2, bin) - BOOST_SPIRIT_X3_UINT_PARSER(unsigned, 8, oct) - BOOST_SPIRIT_X3_UINT_PARSER(unsigned, 16, hex) + using bin_type = uint_parser; + inline constexpr bin_type bin{}; -#undef BOOST_SPIRIT_X3_UINT_PARSER + using oct_type = uint_parser; + inline constexpr oct_type oct{}; + using hex_type = uint_parser; + inline constexpr hex_type hex{}; + } // cpos -}}} +} // boost::spirit::x3 #endif diff --git a/include/boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp b/include/boost/spirit/home/x3/support/numeric_utils/detail/extract_int_impl.hpp similarity index 51% rename from include/boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp rename to include/boost/spirit/home/x3/support/numeric_utils/detail/extract_int_impl.hpp index a256cc5f2a..55a86cc987 100644 --- a/include/boost/spirit/home/x3/support/numeric_utils/detail/extract_int.hpp +++ b/include/boost/spirit/home/x3/support/numeric_utils/detail/extract_int_impl.hpp @@ -9,7 +9,7 @@ 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) =============================================================================*/ -#if !defined(BOOST_SPIRIT_X3_DETAIL_EXTRACT_INT_APRIL_17_2006_0816AM) +#ifndef BOOST_SPIRIT_X3_DETAIL_EXTRACT_INT_APRIL_17_2006_0816AM #define BOOST_SPIRIT_X3_DETAIL_EXTRACT_INT_APRIL_17_2006_0816AM #include @@ -24,33 +24,23 @@ #include #include -#include +#include +#include +#include +#include -#include -#include -#include - -#include -#include -#include - -#include // for std::iterator_traits - -#if !defined(SPIRIT_NUMERICS_LOOP_UNROLL) -# define SPIRIT_NUMERICS_LOOP_UNROLL 3 +#ifndef BOOST_SPIRIT_X3_NUMERICS_LOOP_UNROLL +# define BOOST_SPIRIT_X3_NUMERICS_LOOP_UNROLL 3 #endif -namespace boost { namespace spirit { namespace x3 { namespace detail +namespace boost::spirit::x3::detail { - /////////////////////////////////////////////////////////////////////////// - // - // The maximum radix digits that can be represented without - // overflow: + // The maximum radix digits that can be represented without + // overflow: // - // template - // struct digits_traits::value; + // template + // struct digits_traits::value; // - /////////////////////////////////////////////////////////////////////////// template struct digits_traits; @@ -64,54 +54,41 @@ namespace boost { namespace spirit { namespace x3 { namespace detail (3807350)(3906890)(4000000)(4087460)(4169920)(4247920) \ (4321920)(4392310)(4459430)(4523560)(4584960)(4643850) \ (4700430)(4754880)(4807350)(4857980)(4906890)(4954190) \ - (5000000)(5044390)(5087460)(5129280)(5169925) \ - /***/ + (5000000)(5044390)(5087460)(5129280)(5169925) +#undef BOOST_PP_LOCAL_MACRO #define BOOST_PP_LOCAL_MACRO(Radix) \ template struct digits2_to_n \ { \ - BOOST_STATIC_CONSTANT(int, value = static_cast( \ + static constexpr int value = static_cast( \ (Digits * 1000000) / \ - BOOST_PP_SEQ_ELEM(Radix, BOOST_SPIRIT_X3_LOG2))); \ - }; \ - /***/ + BOOST_PP_SEQ_ELEM(Radix, BOOST_SPIRIT_X3_LOG2)); \ + }; #define BOOST_PP_LOCAL_LIMITS (2, 36) #include BOOST_PP_LOCAL_ITERATE() +#undef BOOST_PP_LOCAL_MACRO #undef BOOST_SPIRIT_X3_LOG2 template struct digits_traits : digits2_to_n::digits, Radix> { - static_assert(std::numeric_limits::radix == 2, ""); + static_assert(std::numeric_limits::radix == 2, "Radix should be 2"); }; template struct digits_traits { - static int constexpr value = std::numeric_limits::digits10; + static constexpr int value = std::numeric_limits::digits10; }; - /////////////////////////////////////////////////////////////////////////// - // - // Traits class for radix specific number conversion - // - // Test the validity of a single character: - // - // template static bool is_valid(Char ch); - // - // Convert a digit from character representation to binary - // representation: - // - // template static int digit(Char ch); - // - /////////////////////////////////////////////////////////////////////////// + // Traits class for radix specific number conversion template struct radix_traits { template - inline static bool is_valid(Char ch) + [[nodiscard]] static constexpr bool is_valid(Char ch) noexcept { return (ch >= '0' && ch <= (Radix > 10 ? '9' : static_cast('0' + Radix -1))) || (Radix > 10 && ch >= 'a' && ch <= static_cast('a' + Radix -10 -1)) @@ -119,7 +96,8 @@ namespace boost { namespace spirit { namespace x3 { namespace detail } template - inline static unsigned digit(Char ch) + [[nodiscard]] static constexpr unsigned digit(Char ch) + noexcept(noexcept(traits::char_encoding_traits::encoding_type::tolower(ch))) { return (Radix <= 10 || (ch >= '0' && ch <= '9')) ? ch - '0' @@ -127,139 +105,126 @@ namespace boost { namespace spirit { namespace x3 { namespace detail } }; - /////////////////////////////////////////////////////////////////////////// - // positive_accumulator/negative_accumulator: Accumulator policies for - // extracting integers. Use positive_accumulator if number is positive. - // Use negative_accumulator if number is negative. - /////////////////////////////////////////////////////////////////////////// + // Accumulator policies for extracting integer from a positive number. template struct positive_accumulator { template - inline static void add(T& n, Char ch, mpl::false_) // unchecked add + static constexpr void unchecked_add(T& n, Char ch) + noexcept(noexcept(radix_traits::digit(ch))) { - const int digit = radix_traits::digit(ch); - n = n * T(Radix) + T(digit); + n = n * T(Radix) + T(radix_traits::digit(ch)); } template - inline static bool add(T& n, Char ch, mpl::true_) // checked add + [[nodiscard]] static constexpr bool checked_add(T& n, Char ch) + noexcept(noexcept(radix_traits::digit(ch))) { // Ensure n *= Radix will not overflow T const max = (std::numeric_limits::max)(); T const val = max / Radix; - if (n > val) - return false; + if (n > val) return false; T tmp = n * Radix; // Ensure n += digit will not overflow - const int digit = radix_traits::digit(ch); - if (tmp > max - digit) - return false; + int const digit = radix_traits::digit(ch); + if (tmp > max - digit) return false; n = tmp + static_cast(digit); return true; } }; + // Accumulator policies for extracting integer from a negative number. template struct negative_accumulator { template - inline static void add(T& n, Char ch, mpl::false_) // unchecked subtract + static constexpr void unchecked_add(T& n, Char ch) + noexcept(noexcept(radix_traits::digit(ch))) { - const int digit = radix_traits::digit(ch); - n = n * T(Radix) - T(digit); + n = n * T(Radix) - T(radix_traits::digit(ch)); } template - inline static bool add(T& n, Char ch, mpl::true_) // checked subtract + [[nodiscard]] static constexpr bool checked_add(T& n, Char ch) + noexcept(noexcept(radix_traits::digit(ch))) { // Ensure n *= Radix will not underflow T const min = (std::numeric_limits::min)(); T const val = min / T(Radix); - if (n < val) - return false; + if (n < val) return false; T tmp = n * Radix; // Ensure n -= digit will not underflow int const digit = radix_traits::digit(ch); - if (tmp < min + digit) - return false; + if (tmp < min + digit) return false; n = tmp - static_cast(digit); return true; } }; - /////////////////////////////////////////////////////////////////////////// - // Common code for extract_int::parse specializations - /////////////////////////////////////////////////////////////////////////// + // Common code for `extract_int::parse` specializations template struct int_extractor { + template + static constexpr bool need_check_overflow = + ( + (MaxDigits < 0) || + (MaxDigits > digits_traits::value) + ) && + traits::check_overflow::value; + template - inline static bool - call(Char ch, std::size_t count, T& n, mpl::true_) + requires need_check_overflow + [[nodiscard]] static constexpr bool + call(Char ch, std::size_t count, T& n) { - std::size_t constexpr - overflow_free = digits_traits::value - 1; + constexpr std::size_t overflow_free = digits_traits::value - 1; if (count < overflow_free) { - Accumulator::add(n, ch, mpl::false_()); + Accumulator::unchecked_add(n, ch); } else { - if (!Accumulator::add(n, ch, mpl::true_())) - return false; // over/underflow! + if (!Accumulator::checked_add(n, ch)) + { + return false; // overflow/underflow + } } return true; } template - inline static bool - call(Char ch, std::size_t /*count*/, T& n, mpl::false_) + requires (!need_check_overflow) + [[nodiscard]] static constexpr bool + call(Char ch, std::size_t /*count*/, T& n) { - // no need to check for overflow - Accumulator::add(n, ch, mpl::false_()); + Accumulator::unchecked_add(n, ch); return true; } template - inline static bool - call(Char /*ch*/, std::size_t /*count*/, unused_type, mpl::false_) + [[nodiscard]] static constexpr bool + call(Char /*ch*/, std::size_t /*count*/, unused_type&) { return true; } - - template - inline static bool - call(Char ch, std::size_t count, T& n) - { - return call(ch, count, n - , mpl::bool_< - ( (MaxDigits < 0) - || (MaxDigits > digits_traits::value) - ) - && traits::check_overflow::value - >() - ); - } }; - /////////////////////////////////////////////////////////////////////////// - // End of loop checking: check if the number of digits - // being parsed exceeds MaxDigits. Note: if MaxDigits == -1 - // we don't do any checking. - /////////////////////////////////////////////////////////////////////////// + // End of loop checking: check if the number of digits + // being parsed exceeds `MaxDigits`. Note: if `MaxDigits == -1` + // we don't do any checking. template struct check_max_digits { - inline static bool - call(std::size_t count) + [[nodiscard]] static constexpr bool + call(std::size_t count) noexcept { return count < MaxDigits; // bounded } @@ -268,17 +233,15 @@ namespace boost { namespace spirit { namespace x3 { namespace detail template <> struct check_max_digits<-1> { - inline static bool - call(std::size_t /*count*/) + [[nodiscard]] static constexpr bool + call(std::size_t /*count*/) noexcept { return true; // unbounded } }; - /////////////////////////////////////////////////////////////////////////// - // extract_int: main code for extracting integers - /////////////////////////////////////////////////////////////////////////// -#define SPIRIT_NUMERIC_INNER_LOOP(z, x, data) \ + // extract_int: main code for extracting integers +#define BOOST_SPIRIT_X3_NUMERIC_INNER_LOOP(z, x, data) \ if (!check_max_digits::call(count + leading_zeros) \ || it == last) \ break; \ @@ -286,13 +249,12 @@ namespace boost { namespace spirit { namespace x3 { namespace detail if (!radix_check::is_valid(ch) || !extractor::call(ch, count, val)) \ break; \ ++it; \ - ++count; \ - /**/ + ++count; template < - typename T, unsigned Radix, unsigned MinDigits, int MaxDigits - , typename Accumulator = positive_accumulator - , bool Accumulate = false + typename T, unsigned Radix, unsigned MinDigits, int MaxDigits, + typename Accumulator = positive_accumulator, + bool Accumulate = false > struct extract_int { @@ -301,22 +263,18 @@ namespace boost { namespace spirit { namespace x3 { namespace detail # pragma warning(disable: 4127) // conditional expression is constant # pragma warning(disable: 4459) // declaration hides global declaration #endif - template - inline static bool - parse_main( - Iterator& first - , Iterator const& last - , Attribute& attr) + template Se, typename Attribute> + [[nodiscard]] static constexpr bool + parse_main(It& first, Se const& last, Attribute& attr) + // TODO: noexcept { - typedef radix_traits radix_check; - typedef int_extractor extractor; - typedef typename - std::iterator_traits::value_type - char_type; + using radix_check = radix_traits; + using extractor = int_extractor; + using char_type = std::iter_value_t; - Iterator it = first; + It it = first; std::size_t leading_zeros = 0; - if (!Accumulate) + if constexpr (!Accumulate) { // skip leading zeros while (it != last && *it == '0' && leading_zeros < MaxDigits) @@ -326,19 +284,14 @@ namespace boost { namespace spirit { namespace x3 { namespace detail } } - typedef typename - traits::attribute_type::type - attribute_type; - + using attribute_type = traits::attribute_type_t; attribute_type val = Accumulate ? attr : attribute_type(0); std::size_t count = 0; char_type ch; while (true) { - BOOST_PP_REPEAT( - SPIRIT_NUMERICS_LOOP_UNROLL - , SPIRIT_NUMERIC_INNER_LOOP, _) + BOOST_PP_REPEAT(BOOST_SPIRIT_X3_NUMERICS_LOOP_UNROLL, BOOST_SPIRIT_X3_NUMERIC_INNER_LOOP, _) } if (count + leading_zeros >= MinDigits) @@ -353,34 +306,31 @@ namespace boost { namespace spirit { namespace x3 { namespace detail # pragma warning(pop) #endif - template - inline static bool - parse( - Iterator& first - , Iterator const& last - , unused_type) + template Se> + [[nodiscard]] static constexpr bool + parse(It& first, Se const& last, unused_type) + noexcept( + std::is_nothrow_constructible_v && + noexcept(extract_int::parse_main(first, last, std::declval())) + ) { - T n = 0; // must calculate value to detect over/underflow - return parse_main(first, last, n); + T n(0); // must calculate value to detect over/underflow + return extract_int::parse_main(first, last, n); } - template - inline static bool - parse( - Iterator& first - , Iterator const& last - , Attribute& attr) + template Se, typename Attribute> + [[nodiscard]] static constexpr bool + parse(It& first, Se const& last, Attribute& attr) + noexcept(noexcept(extract_int::parse_main(first, last, attr))) { - return parse_main(first, last, attr); + return extract_int::parse_main(first, last, attr); } }; -#undef SPIRIT_NUMERIC_INNER_LOOP +#undef BOOST_SPIRIT_X3_NUMERIC_INNER_LOOP - /////////////////////////////////////////////////////////////////////////// - // extract_int: main code for extracting integers - // common case where MinDigits == 1 and MaxDigits = -1 - /////////////////////////////////////////////////////////////////////////// -#define SPIRIT_NUMERIC_INNER_LOOP(z, x, data) \ + // extract_int: main code for extracting integers + // common case where MinDigits == 1 and MaxDigits = -1 +#define BOOST_SPIRIT_X3_NUMERIC_INNER_LOOP(z, x, data) \ if (it == last) \ break; \ ch = *it; \ @@ -389,8 +339,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail if (!extractor::call(ch, count, val)) \ return false; \ ++it; \ - ++count; \ - /**/ + ++count; template struct extract_int @@ -400,22 +349,18 @@ namespace boost { namespace spirit { namespace x3 { namespace detail # pragma warning(disable: 4127) // conditional expression is constant # pragma warning(disable: 4459) // declaration hides global declaration #endif - template - inline static bool - parse_main( - Iterator& first - , Iterator const& last - , Attribute& attr) + template Se, typename Attribute> + [[nodiscard]] static constexpr bool + parse_main(It& first, Se const& last, Attribute& attr) + // TODO: noexcept { - typedef radix_traits radix_check; - typedef int_extractor extractor; - typedef typename - std::iterator_traits::value_type - char_type; + using radix_check = radix_traits; + using extractor = int_extractor; + using char_type = std::iter_value_t; - Iterator it = first; + It it = first; std::size_t count = 0; - if (!Accumulate) + if constexpr (!Accumulate) { // skip leading zeros while (it != last && *it == '0') @@ -426,25 +371,20 @@ namespace boost { namespace spirit { namespace x3 { namespace detail if (it == last) { - if (count == 0) // must have at least one digit - return false; + if (count == 0) return false; // must have at least one digit attr = 0; first = it; return true; } } - typedef typename - traits::attribute_type::type - attribute_type; - + using attribute_type = traits::attribute_type_t; attribute_type val = Accumulate ? attr : attribute_type(0); - char_type ch = *it; + char_type ch = *it; if (!radix_check::is_valid(ch) || !extractor::call(ch, 0, val)) { - if (count == 0) // must have at least one digit - return false; + if (count == 0) return false; // must have at least one digit traits::move_to(std::move(val), attr); first = it; return true; @@ -454,9 +394,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail ++it; while (true) { - BOOST_PP_REPEAT( - SPIRIT_NUMERICS_LOOP_UNROLL - , SPIRIT_NUMERIC_INNER_LOOP, _) + BOOST_PP_REPEAT(BOOST_SPIRIT_X3_NUMERICS_LOOP_UNROLL, BOOST_SPIRIT_X3_NUMERIC_INNER_LOOP, _) } traits::move_to(std::move(val), attr); @@ -467,29 +405,28 @@ namespace boost { namespace spirit { namespace x3 { namespace detail # pragma warning(pop) #endif - template - inline static bool - parse( - Iterator& first - , Iterator const& last - , unused_type) + template Se> + [[nodiscard]] static constexpr bool + parse(It& first, Se const& last, unused_type) + noexcept( + std::is_nothrow_constructible_v && + noexcept(extract_int::parse_main(first, last, std::declval())) + ) { - T n = 0; // must calculate value to detect over/underflow - return parse_main(first, last, n); + T n(0); // must calculate value to detect over/underflow + return extract_int::parse_main(first, last, n); } - template - inline static bool - parse( - Iterator& first - , Iterator const& last - , Attribute& attr) + template Se, typename Attribute> + [[nodiscard]] static constexpr bool + parse(It& first, Se const& last, Attribute& attr) + noexcept(noexcept(extract_int::parse_main(first, last, attr))) { - return parse_main(first, last, attr); + return extract_int::parse_main(first, last, attr); } }; -#undef SPIRIT_NUMERIC_INNER_LOOP -}}}} +#undef BOOST_SPIRIT_X3_NUMERIC_INNER_LOOP +} // boost::spirit::x3::detail #endif diff --git a/include/boost/spirit/home/x3/support/numeric_utils/extract_int.hpp b/include/boost/spirit/home/x3/support/numeric_utils/extract_int.hpp index d0e1e07c6a..fc1f514a9f 100644 --- a/include/boost/spirit/home/x3/support/numeric_utils/extract_int.hpp +++ b/include/boost/spirit/home/x3/support/numeric_utils/extract_int.hpp @@ -6,63 +6,64 @@ 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) ==============================================================================*/ -#if !defined(BOOST_SPIRIT_X3_EXTRACT_INT_APRIL_17_2006_0830AM) +#ifndef BOOST_SPIRIT_X3_EXTRACT_INT_APRIL_17_2006_0830AM #define BOOST_SPIRIT_X3_EXTRACT_INT_APRIL_17_2006_0830AM #include -#include +#include #include -namespace boost { namespace spirit { namespace x3 +#include +#include + +namespace boost::spirit::x3 { - /////////////////////////////////////////////////////////////////////////// - // Extract the prefix sign (- or +), return true if a '-' was found - /////////////////////////////////////////////////////////////////////////// - template - inline bool - extract_sign(Iterator& first, Iterator const& last) + namespace detail { - (void)last; // silence unused warnings - BOOST_ASSERT(first != last); // precondition - - // Extract the sign - bool neg = *first == '-'; - if (neg || (*first == '+')) + // Extract the prefix sign (- or +), return true if a '-' was found + template Se> + [[nodiscard]] constexpr bool + extract_sign(It& first, Se const& last) + noexcept( + noexcept(*first) && + noexcept(++first) + ) { - ++first; - return neg; + (void)last; + BOOST_ASSERT(first != last); // precondition + + // Extract the sign + bool const neg = *first == '-'; + if (neg || (*first == '+')) + { + ++first; + return neg; + } + return false; } - return false; - } + } // detail - /////////////////////////////////////////////////////////////////////////// // Low level unsigned integer parser - /////////////////////////////////////////////////////////////////////////// - template + template struct extract_uint { // check template parameter 'Radix' for validity - static_assert( - (Radix >= 2 && Radix <= 36), - "Error Unsupported Radix"); - - template - inline static bool call(Iterator& first, Iterator const& last, T& attr) + static_assert(Radix >= 2 && Radix <= 36, "Unsupported Radix"); + + using extract_type = detail::extract_int< + T, Radix, MinDigits, MaxDigits, + detail::positive_accumulator, + Accumulate + >; + + template Se> + [[nodiscard]] static constexpr bool + call(It& first, Se const& last, T& attr) + noexcept(std::is_nothrow_copy_assignable_v && noexcept(extract_type::parse(first, last, attr))) { - if (first == last) - return false; + if (first == last) return false; - typedef detail::extract_int< - T - , Radix - , MinDigits - , MaxDigits - , detail::positive_accumulator - , Accumulate> - extract_type; - - Iterator save = first; + It const save = first; if (!extract_type::parse(first, last, attr)) { first = save; @@ -71,51 +72,61 @@ namespace boost { namespace spirit { namespace x3 return true; } - template - inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_) + template Se, typename Attribute> + [[nodiscard]] static constexpr bool + call(It& first, Se const& last, Attribute& attr) + noexcept( + std::is_nothrow_default_constructible_v && + noexcept(extract_uint::call(first, last, std::declval())) && + noexcept(traits::move_to(std::declval(), attr)) + ) { // this case is called when Attribute is not T - T attr; - if (call(first, last, attr)) + T tmp_attr; // default initialize + if (extract_uint::call(first, last, tmp_attr)) { - traits::move_to(std::move(attr), attr_); + traits::move_to(std::move(tmp_attr), attr); return true; } return false; } }; - /////////////////////////////////////////////////////////////////////////// // Low level signed integer parser - /////////////////////////////////////////////////////////////////////////// template struct extract_int { // check template parameter 'Radix' for validity static_assert( - (Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16), - "Error Unsupported Radix"); - - template - inline static bool call(Iterator& first, Iterator const& last, T& attr) + Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16, + "Unsupported Radix" + ); + + using extract_pos_type = detail::extract_int; + using extract_neg_type = detail::extract_int>; + + template Se> + [[nodiscard]] static constexpr bool + call(It& first, Se const& last, T& attr) + noexcept( + std::is_nothrow_copy_assignable_v && + noexcept(detail::extract_sign(first, last)) && + noexcept(extract_neg_type::parse(first, last, attr)) && + noexcept(extract_pos_type::parse(first, last, attr)) + ) { - if (first == last) - return false; - - typedef detail::extract_int< - T, Radix, MinDigits, MaxDigits> - extract_pos_type; - - typedef detail::extract_int< - T, Radix, MinDigits, MaxDigits, detail::negative_accumulator > - extract_neg_type; + if (first == last) return false; - Iterator save = first; - bool hit = extract_sign(first, last); + It const save = first; + bool hit = detail::extract_sign(first, last); if (hit) + { hit = extract_neg_type::parse(first, last, attr); + } else + { hit = extract_pos_type::parse(first, last, attr); + } if (!hit) { @@ -125,19 +136,25 @@ namespace boost { namespace spirit { namespace x3 return true; } - template - inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_) + template Se, typename Attribute> + [[nodiscard]] static constexpr bool + call(It& first, Se const& last, Attribute& attr) + noexcept( + std::is_nothrow_default_constructible_v && + noexcept(extract_int::call(first, last, std::declval())) && + noexcept(traits::move_to(std::declval(), attr)) + ) { // this case is called when Attribute is not T - T attr; - if (call(first, last, attr)) + T tmp_attr; // default initialize + if (extract_int::call(first, last, tmp_attr)) { - traits::move_to(std::move(attr), attr_); + traits::move_to(std::move(tmp_attr), attr); return true; } return false; } }; -}}} +} // boost::spirit::x3 #endif diff --git a/include/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp b/include/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp index 4ce8ea2771..07e26c6ca0 100644 --- a/include/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp +++ b/include/boost/spirit/home/x3/support/numeric_utils/extract_real.hpp @@ -1,34 +1,35 @@ /*============================================================================= Copyright (c) 2001-2014 Joel de Guzman Copyright (c) 2001-2011 Hartmut Kaiser - http://spirit.sourceforge.net/ + Copyright (c) 2025 Nana Sakisaka 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) =============================================================================*/ -#if !defined(BOOST_SPIRIT_X3_EXTRACT_REAL_APRIL_18_2006_0901AM) +#ifndef BOOST_SPIRIT_X3_EXTRACT_REAL_APRIL_18_2006_0901AM #define BOOST_SPIRIT_X3_EXTRACT_REAL_APRIL_18_2006_0901AM -#include -#include -#include #include #include #include #include +#include +#include +#include + +#include + +// TODO: fix this #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) # pragma warning(push) # pragma warning(disable: 4100) // 'p': unreferenced formal parameter -# pragma warning(disable: 4127) // conditional expression is constant #endif -namespace boost { namespace spirit { namespace x3 { namespace extension +namespace boost::spirit::x3::extension { - using x3::traits::pow10; - template - inline bool + [[nodiscard]] constexpr bool scale(int exp, T& n) { constexpr auto max_exp = std::numeric_limits::max_exponent10; @@ -38,99 +39,109 @@ namespace boost { namespace spirit { namespace x3 { namespace extension { // return false if exp exceeds the max_exp // do this check only for primitive types! - if (is_floating_point() && exp > max_exp) - return false; - n *= pow10(exp); + if constexpr (std::is_floating_point_v) + { + if (exp > max_exp) + { + return false; + } + } + n *= traits::pow10(exp); } else { if (exp < min_exp) { - n /= pow10(-min_exp); + n /= traits::pow10(-min_exp); // return false if exp still exceeds the min_exp // do this check only for primitive types! exp += -min_exp; - if (is_floating_point() && exp < min_exp) - return false; - n /= pow10(-exp); + if constexpr (std::is_floating_point_v) + { + if (exp < min_exp) + { + return false; + } + } + + n /= traits::pow10(-exp); } else { - n /= pow10(-exp); + n /= traits::pow10(-exp); } } return true; } - inline bool - scale(int /*exp*/, unused_type /*n*/) + [[nodiscard]] constexpr bool + scale(int /*exp*/, unused_type /*n*/) noexcept { // no-op for unused_type return true; } template - inline bool - scale(int exp, int frac, T& n) + [[nodiscard]] constexpr bool + scale(int exp, int frac, T& n) noexcept { - return scale(exp - frac, n); + return extension::scale(exp - frac, n); } - inline bool - scale(int /*exp*/, int /*frac*/, unused_type /*n*/) + [[nodiscard]] constexpr bool + scale(int /*exp*/, int /*frac*/, unused_type /*n*/) noexcept { // no-op for unused_type return true; } - inline float - negate(bool neg, float n) + [[nodiscard]] inline /* constexpr */ float // TODO: constexpr + negate(bool neg, float n) noexcept { return neg ? (std::copysignf)(n, -1.f) : n; } - inline double - negate(bool neg, double n) + [[nodiscard]] inline /* constexpr */ double // TODO: constexpr + negate(bool neg, double n) noexcept { return neg ? (std::copysign)(n, -1.) : n; } - inline long double - negate(bool neg, long double n) + [[nodiscard]] inline /* constexpr */ long double // TODO: constexpr + negate(bool neg, long double n) noexcept { return neg ? (std::copysignl)(n, -1.) : n; } template - inline T - negate(bool neg, T const& n) + [[nodiscard]] constexpr T + negate(bool neg, T const& n) noexcept { return neg ? -n : n; } - inline unused_type - negate(bool /*neg*/, unused_type n) + [[nodiscard]] constexpr unused_type + negate(bool /*neg*/, unused_type n) noexcept { // no-op for unused_type return n; } -}}}} +} // boost::spirit::x3::extension -namespace boost { namespace spirit { namespace x3 +namespace boost::spirit::x3 { template struct extract_real { - template - static bool - parse(Iterator& first, Iterator const& last, Attribute& attr, - RealPolicies const& p) + template Se, typename Attribute> + [[nodiscard]] static constexpr bool + parse(It& first, Se const& last, Attribute& attr, RealPolicies const& p) + // TODO: noexcept { - if (first == last) - return false; - Iterator save = first; + if (first == last) return false; + It save = first; // Start by parsing the sign. neg will be true if // we got a "-" sign, false otherwise. @@ -163,7 +174,7 @@ namespace boost { namespace spirit { namespace x3 } bool e_hit = false; - Iterator e_pos; + It e_pos; int frac_digits = 0; // Try to parse the dot ('.' decimal point) @@ -172,14 +183,15 @@ namespace boost { namespace spirit { namespace x3 // We got the decimal point. Now we will try to parse // the fraction if it is there. If not, it defaults // to zero (0) only if we already got a number. - Iterator savef = first; + It savef = first; if (p.parse_frac_n(first, last, n)) { // Optimization note: don't compute frac_digits if T is // an unused_type. This should be optimized away by the compiler. - if (!is_same::value) - frac_digits = - static_cast(std::distance(savef, first)); + if constexpr (!std::is_same_v) + { + frac_digits = static_cast(std::distance(savef, first)); + } BOOST_ASSERT(frac_digits >= 0); } else if (!got_a_number || !p.allow_trailing_dot) @@ -257,6 +269,6 @@ namespace boost { namespace spirit { namespace x3 # pragma warning(pop) #endif -}}} +} // boost::spirit::x3 #endif diff --git a/include/boost/spirit/home/x3/support/numeric_utils/pow10.hpp b/include/boost/spirit/home/x3/support/numeric_utils/pow10.hpp index eb40dd28a0..ad5e5b2c62 100644 --- a/include/boost/spirit/home/x3/support/numeric_utils/pow10.hpp +++ b/include/boost/spirit/home/x3/support/numeric_utils/pow10.hpp @@ -1,113 +1,120 @@ /*============================================================================= Copyright (c) 2001-2014 Joel de Guzman Copyright (c) 2001-2011 Hartmut Kaiser - http://spirit.sourceforge.net/ + Copyright (c) 2025 Nana Sakisaka 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) =============================================================================*/ -#if !defined(BOOST_SPIRIT_X3_POW10_DECEMBER_26_2008_1118AM) +#ifndef BOOST_SPIRIT_X3_POW10_DECEMBER_26_2008_1118AM #define BOOST_SPIRIT_X3_POW10_DECEMBER_26_2008_1118AM -#include -#include #include #include -#include -#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) -# pragma warning(push) -# pragma warning(disable: 4244) // conversion from 'double' to 'float', possible loss of data -#endif +#include + +#include +#include -namespace boost { namespace spirit { namespace x3 { namespace traits +namespace boost::spirit::x3::traits { namespace detail { - template - struct pow10_helper + namespace pow10_helper_impl { - static T call(unsigned dim) - { - using namespace std; // allow for ADL to find the correct overload - return pow(T(10), T(dim)); - } - }; + using namespace std; // fallback + + template + concept HasPow = requires(T base_, T exp_) { + { pow(base_, exp_) } -> std::convertible_to; + }; - template <> - struct pow10_helper + } // pow10_helper_impl + + } // detail + + template + requires detail::pow10_helper_impl::HasPow + struct pow10_helper + { + [[nodiscard]] static constexpr T call(unsigned dim) noexcept { - static unused_type call(unused_type) - { - return unused; - } - }; + using namespace std; // fallback + return pow(T(10), T(dim)); + } + }; -#if (DBL_MAX_10_EXP == 308) // for IEEE-754 - template <> - struct pow10_helper + template <> + struct pow10_helper + { + [[nodiscard]] static constexpr unused_type call(unused_type) noexcept { - static double call(unsigned dim) - { - static double const exponents[] = - { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, - 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, - 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, - 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, - 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59, - 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, - 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79, - 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89, - 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99, - 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, - 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, - 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, - 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, - 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, - 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, - 1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169, - 1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179, - 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189, - 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199, - 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209, - 1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219, - 1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229, - 1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239, - 1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249, - 1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259, - 1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269, - 1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279, - 1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289, - 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299, - 1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308, - }; - BOOST_ASSERT(dim < sizeof(exponents)/sizeof(double)); - return exponents[dim]; - } - }; + return unused; + } + }; - template <> - struct pow10_helper +#if DBL_MAX_10_EXP == 308 // for IEEE-754 + template <> + struct pow10_helper + { + inline static constexpr double exponents[] = { - static float call(unsigned dim) - { - return pow10_helper::call(dim); - } + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, + 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, + 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, + 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59, + 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, + 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79, + 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89, + 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99, + 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, + 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, + 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, + 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, + 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, + 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, + 1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169, + 1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179, + 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189, + 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199, + 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209, + 1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219, + 1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229, + 1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239, + 1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249, + 1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259, + 1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269, + 1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279, + 1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289, + 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299, + 1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308, }; + + [[nodiscard]] static constexpr double call(unsigned dim) noexcept + { + BOOST_ASSERT(dim < sizeof(exponents)/sizeof(double)); + return exponents[dim]; + } + }; + + template <> + struct pow10_helper + { + [[nodiscard]] static constexpr float call(unsigned dim) noexcept + { + return static_cast(pow10_helper::call(dim)); + } + }; #endif // for IEEE-754 - } template - inline T pow10(unsigned dim) + [[nodiscard]] constexpr T pow10(unsigned dim) noexcept { - return detail::pow10_helper::call(dim); + return pow10_helper::call(dim); } -}}}} - -#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) -# pragma warning(pop) -#endif +} #endif diff --git a/include/boost/spirit/home/x3/support/traits/numeric_traits.hpp b/include/boost/spirit/home/x3/support/traits/numeric_traits.hpp index cf4ca933cc..1c059ba55d 100644 --- a/include/boost/spirit/home/x3/support/traits/numeric_traits.hpp +++ b/include/boost/spirit/home/x3/support/traits/numeric_traits.hpp @@ -1,99 +1,63 @@ /*============================================================================= Copyright (c) 2001-2011 Hartmut Kaiser + Copyright (c) 2025 Nana Sakisaka 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) ==============================================================================*/ -#if !defined(BOOST_SPIRIT_X3_NUMERIC_TRAITS_JAN_07_2011_0722AM) +#ifndef BOOST_SPIRIT_X3_NUMERIC_TRAITS_JAN_07_2011_0722AM #define BOOST_SPIRIT_X3_NUMERIC_TRAITS_JAN_07_2011_0722AM #include -#include + #include +#include -namespace boost { namespace spirit { namespace x3 { namespace traits +namespace boost::spirit::x3::traits { - /////////////////////////////////////////////////////////////////////////// // Determine if T is a boolean type - /////////////////////////////////////////////////////////////////////////// template - struct is_bool : mpl::false_ {}; + struct is_bool : std::is_same {}; + + template + constexpr bool is_bool_v = is_bool::value; template struct is_bool : is_bool {}; - template <> - struct is_bool : mpl::true_ {}; - - /////////////////////////////////////////////////////////////////////////// // Determine if T is a signed integer type - /////////////////////////////////////////////////////////////////////////// template - struct is_int : mpl::false_ {}; + struct is_int : std::is_signed {}; + + template + constexpr bool is_int_v = is_int::value; template struct is_int : is_int {}; - template <> - struct is_int : mpl::true_ {}; - - template <> - struct is_int : mpl::true_ {}; - - template <> - struct is_int : mpl::true_ {}; - -#ifdef BOOST_HAS_LONG_LONG - template <> - struct is_int : mpl::true_ {}; -#endif - - /////////////////////////////////////////////////////////////////////////// // Determine if T is an unsigned integer type - /////////////////////////////////////////////////////////////////////////// template - struct is_uint : mpl::false_ {}; + struct is_uint : std::is_unsigned {}; template struct is_uint : is_uint {}; -#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) - template <> - struct is_uint : mpl::true_ {}; -#endif - - template <> - struct is_uint : mpl::true_ {}; - - template <> - struct is_uint : mpl::true_ {}; - -#ifdef BOOST_HAS_LONG_LONG - template <> - struct is_uint : mpl::true_ {}; -#endif + template + constexpr bool is_uint_v = is_uint::value; - /////////////////////////////////////////////////////////////////////////// // Determine if T is a floating point type - /////////////////////////////////////////////////////////////////////////// template - struct is_real : mpl::false_ {}; + struct is_real : std::is_floating_point {}; template - struct is_real : is_uint {}; - - template <> - struct is_real : mpl::true_ {}; + struct is_real : is_real {}; - template <> - struct is_real : mpl::true_ {}; + template + constexpr bool is_real_v = is_real::value; - template <> - struct is_real : mpl::true_ {}; + // -------------------------------------------------- - /////////////////////////////////////////////////////////////////////////// - // customization points for numeric operations - /////////////////////////////////////////////////////////////////////////// + // Customization points for numeric operations template struct absolute_value; @@ -113,7 +77,8 @@ namespace boost { namespace spirit { namespace x3 { namespace traits struct is_infinite; template - struct check_overflow : mpl::bool_::is_bounded> {}; -}}}} + struct check_overflow : std::bool_constant::is_bounded> {}; + +} // boost::spirit::x3::traits #endif