> Oh actually the radix members should be of type int, not bool. I can fix
that.

Yes - thank you very much Jonathan for catching that!
It was my honest oversight - I am so used to using auto, that I have
accidentally copied the wrong type.
Also, thank you for adding tests - I should have added them myself in the
first place.

> Thanks, I don't think there was any reason to omit these members,
> and I agree we should add them.

Regarding adding missing members,
I am wondering whether template specializations of std::numeric_limits<>
for integer-class types
should define remaining static data members and static member functions,
that is:
- max_digits10
- traps
- is_iec559
- round_style
 - has_infinity
- has_quiet_NaN
- has_signaling_NaN
- has_denorm
- has_denorm_loss
- min_exponent
- min_exponent10
- max_exponent
- max_exponent10
- tinyness_before
 - epsilon()
- round_error()
- infinity()
- quiet_NaN()
- signaling_NaN()
- denorm_min()

Here are reading relevant sections of the C++ standard:

  25.3.4.4 Concept weakly_incrementable      [iterator.concept.winc]

  (5) For every integer-class type I,
      let B(I) be a unique hypothetical extended integer type
      of the same signedness with the same width as I.

      [Note 2: The corresponding
               hypothetical specialization numeric_limits<B(I)>
               meets the requirements on
               numeric_limits specializations for integral types.]

 (11) For every (possibly cv-qualified) integer-class type I,
      numeric_limits<I> is specialized such that:

      - each static data member m
        has the same value as numeric_limits<B(I)>::m, and

      - each static member function f
        returns I(numeric_limits<B(I)>::f()).

In short, std::numeric_limits<> specializations for integer-class types
should be defined
identically to std::numeric_limits<> specializations for extended integer
types,
and thus define all static data members and static member functions.
Am I reading this correctly?

Thank you, Mateusz Zych

On Wed, Jul 2, 2025 at 1:59 PM Jonathan Wakely <jwak...@redhat.com> wrote:

> On 02/07/25 11:52 +0100, Jonathan Wakely wrote:
> >On Wed, 2 Jul 2025 at 10:50, Jonathan Wakely <jwak...@redhat.com> wrote:
> >>
> >> On 02/07/25 03:36 +0300, Mateusz Zych wrote:
> >> >Hello libstdc++ Team!
> >> >
> >> >I have recently found a bug in libstdc++, that is,
> >> >the std::numeric_limits<> template specializations for integer-class
> types
> >> >are missing some of static data members,
> >> >which results in compilation errors of valid C++ code:
> >> >
> >> >   - Compiler Explorer: https://godbolt.org/z/E7z4WYfj4
> >> >
> >> >Since adding missing member constants, which are the most relevant to
> >> >integer-like types,
> >> >was not a lot of code, I have prepared a Git patch with relevant
> changes.
> >> >
> >> >I hope this patch is useful, Mateusz Zych
> >>
> >> Thanks, I don't think there was any reason to omit these members, and I
> >> agree we should add them.
> >>
> >> The patch is simple and obvious enough that I don't think we need a
> >> copyright assignment or DCO sign-off, so I'll push this to the
> >> relevant branches. Thanks!
> >
> >Oh actually the radix members should be of type int, not bool. I can fix
> that.
>
> Here's what I'm testing:
>
>
> commit ddd5b88db4fe99166835fe1b94beca451bc1ce30
> Author:     Mateusz Zych <mte.z...@gmail.com>
> AuthorDate: Tue Jul 1 23:51:40 2025
> Commit:     Jonathan Wakely <r...@gcc.gnu.org>
> CommitDate: Wed Jul 2 11:57:45 2025
>
>      libstdc++: Add missing members to numeric_limits specializations for
> integer-class types
>
>      [iterator.concept.winc]/11 says that std::numeric_limits should be
>      specialized for integer-class types, with each member defined
>      appropriately.
>
>      libstdc++-v3/ChangeLog:
>
>              * include/bits/max_size_type.h
> (numeric_limits<__max_size_type>):
>              New static data members.
>              (numeric_limits<__max_diff_type>): Likewise.
>              * testsuite/std/ranges/iota/max_size_type.cc: Check new
> members.
>
>      Co-authored-by: Jonathan Wakely <jwak...@redhat.com>
>
> diff --git a/libstdc++-v3/include/bits/max_size_type.h
> b/libstdc++-v3/include/bits/max_size_type.h
> index 73a6d141d5bc..3ac2b8e6b878 100644
> --- a/libstdc++-v3/include/bits/max_size_type.h
> +++ b/libstdc++-v3/include/bits/max_size_type.h
> @@ -775,6 +775,9 @@ namespace ranges
>         static constexpr bool is_signed = false;
>         static constexpr bool is_integer = true;
>         static constexpr bool is_exact = true;
> +      static constexpr bool is_bounded = true;
> +      static constexpr bool is_modulo = true;
> +      static constexpr int radix = 2;
>         static constexpr int digits
>         = __gnu_cxx::__int_traits<_Sp::__rep>::__digits + 1;
>         static constexpr int digits10
> @@ -802,6 +805,9 @@ namespace ranges
>         static constexpr bool is_signed = true;
>         static constexpr bool is_integer = true;
>         static constexpr bool is_exact = true;
> +      static constexpr bool is_bounded = true;
> +      static constexpr bool is_modulo = false;
> +      static constexpr int radix = 2;
>         static constexpr int digits = numeric_limits<_Sp>::digits - 1;
>         static constexpr int digits10
>         = static_cast<int>(digits * numbers::ln2 / numbers::ln10);
> diff --git a/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc
> b/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc
> index 4739d9e2f790..fc5284594c7e 100644
> --- a/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc
> @@ -352,6 +352,9 @@
> static_assert(numeric_limits<max_size_t>::is_specialized);
>   static_assert(!numeric_limits<max_size_t>::is_signed);
>   static_assert(numeric_limits<max_size_t>::is_integer);
>   static_assert(numeric_limits<max_size_t>::is_exact);
> +static_assert(numeric_limits<max_size_t>::is_bounded);
> +static_assert(numeric_limits<max_size_t>::is_modulo);
> +static_assert(numeric_limits<max_size_t>::radix == 2);
>   // We can't unconditionally use numeric_limits here because __int128 is
> an
>   // integral type only in GNU mode.
>   #if __SIZEOF_INT128__
> @@ -379,6 +382,9 @@
> static_assert(numeric_limits<max_diff_t>::is_specialized);
>   static_assert(numeric_limits<max_diff_t>::is_signed);
>   static_assert(numeric_limits<max_diff_t>::is_integer);
>   static_assert(numeric_limits<max_diff_t>::is_exact);
> +static_assert(numeric_limits<max_diff_t>::is_bounded);
> +static_assert(!numeric_limits<max_diff_t>::is_modulo);
> +static_assert(numeric_limits<max_diff_t>::radix == 2);
>   static_assert(numeric_limits<max_diff_t>::digits
>               == numeric_limits<max_size_t>::digits - 1);
>   static_assert(numeric_limits<max_diff_t>::digits10
>
>

Reply via email to