On Mon, Dec 8, 2025 at 9:05 AM Tomasz Kaminski <[email protected]> wrote:
> > > On Fri, Dec 5, 2025 at 7:01 PM Jonathan Wakely <[email protected]> wrote: > >> This allows the [utility.intcmp] functions to be used without including >> all of <utility>. >> >> libstdc++-v3/ChangeLog: >> >> * include/Makefile.am: Add new header. >> * include/Makefile.in: Regenerate. >> * include/std/latch: Include <bits/intcmp.h> instead of >> <utility>. >> * include/std/utility: Include <bits/intcmp.h>. >> (cmp_equal, cmp_not_equal, cmp_less, cmp_greater) >> (cmp_less_equal, cmp_greater_equal, in_range): Move to ... >> * include/bits/intcmp.h: New file. >> --- >> >> I see that <mdspan> uses these functions, but it also uses std::as_const >> so it needs the entire <utility> header. Maybe we should consider moving >> as_const to <bits/move.h>? It's conceptually a cast like std::move and >> std::forward. >> > I think such a change makes sense. I was going to say that submdspan > introduces > dependency on <tuple> from mdpsan, however I do not think that P3663R3: > Future-proof submdspan_mapping > this is still the case, as we use structure binding to decompose strides. > submdspan_cannonicalize_slices still returns a tuple of new slices, so we still have dependency on the tuple header. > >> Tested x86_64-linux. >> >> libstdc++-v3/include/Makefile.am | 1 + >> libstdc++-v3/include/Makefile.in | 1 + >> libstdc++-v3/include/bits/intcmp.h | 120 +++++++++++++++++++++++++++++ >> libstdc++-v3/include/std/latch | 2 +- >> libstdc++-v3/include/std/utility | 72 +---------------- >> 5 files changed, 124 insertions(+), 72 deletions(-) >> create mode 100644 libstdc++-v3/include/bits/intcmp.h >> >> diff --git a/libstdc++-v3/include/Makefile.am >> b/libstdc++-v3/include/Makefile.am >> index 7d65c6f3ab31..847fc13151f5 100644 >> --- a/libstdc++-v3/include/Makefile.am >> +++ b/libstdc++-v3/include/Makefile.am >> @@ -134,6 +134,7 @@ bits_freestanding = \ >> ${bits_srcdir}/enable_special_members.h \ >> ${bits_srcdir}/functexcept.h \ >> ${bits_srcdir}/functional_hash.h \ >> + ${bits_srcdir}/intcmp.h \ >> ${bits_srcdir}/invoke.h \ >> ${bits_srcdir}/iterator_concepts.h \ >> ${bits_srcdir}/max_size_type.h \ >> diff --git a/libstdc++-v3/include/Makefile.in >> b/libstdc++-v3/include/Makefile.in >> index acf8ae9be441..1d6171bac9d1 100644 >> --- a/libstdc++-v3/include/Makefile.in >> +++ b/libstdc++-v3/include/Makefile.in >> @@ -492,6 +492,7 @@ bits_freestanding = \ >> ${bits_srcdir}/enable_special_members.h \ >> ${bits_srcdir}/functexcept.h \ >> ${bits_srcdir}/functional_hash.h \ >> + ${bits_srcdir}/intcmp.h \ >> ${bits_srcdir}/invoke.h \ >> ${bits_srcdir}/iterator_concepts.h \ >> ${bits_srcdir}/max_size_type.h \ >> diff --git a/libstdc++-v3/include/bits/intcmp.h >> b/libstdc++-v3/include/bits/intcmp.h >> new file mode 100644 >> index 000000000000..3d3fbc43d2c8 >> --- /dev/null >> +++ b/libstdc++-v3/include/bits/intcmp.h >> @@ -0,0 +1,120 @@ >> +// Integer comparison functions -*- C++ -*- >> + >> +// Copyright (C) 2020-2025 Free Software Foundation, Inc. >> +// >> +// This file is part of the GNU ISO C++ Library. This library is free >> +// software; you can redistribute it and/or modify it under the >> +// terms of the GNU General Public License as published by the >> +// Free Software Foundation; either version 3, or (at your option) >> +// any later version. >> + >> +// This library is distributed in the hope that it will be useful, >> +// but WITHOUT ANY WARRANTY; without even the implied warranty of >> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> +// GNU General Public License for more details. >> + >> +// Under Section 7 of GPL version 3, you are granted additional >> +// permissions described in the GCC Runtime Library Exception, version >> +// 3.1, as published by the Free Software Foundation. >> + >> +// You should have received a copy of the GNU General Public License and >> +// a copy of the GCC Runtime Library Exception along with this program; >> +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see >> +// <http://www.gnu.org/licenses/>. >> + >> +/** @file bits/intcmp.h >> + * This is an internal header file, included by other library headers. >> + * Do not attempt to use it directly. @headername{utility} >> + */ >> + >> +#ifndef _GLIBCXX_INTCMP_H >> +#define _GLIBCXX_INTCMP_H 1 >> + >> +#ifdef _GLIBCXX_SYSHDR >> +#pragma GCC system_header >> +#endif >> + >> +#include <bits/version.h> >> + >> +#ifdef __glibcxx_integer_comparison_functions // C++ >= 20 >> + >> +#include <type_traits> >> +#include <ext/numeric_traits.h> // __int_traits >> + >> +namespace std _GLIBCXX_VISIBILITY(default) >> +{ >> +_GLIBCXX_BEGIN_NAMESPACE_VERSION >> + >> + template<typename _Tp, typename _Up> >> + constexpr bool >> + cmp_equal(_Tp __t, _Up __u) noexcept >> + { >> + static_assert(__is_standard_integer<_Tp>::value); >> + static_assert(__is_standard_integer<_Up>::value); >> + >> + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) >> + return __t == __u; >> + else if constexpr (is_signed_v<_Tp>) >> + return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u; >> + else >> + return __u >= 0 && __t == make_unsigned_t<_Up>(__u); >> + } >> + >> + template<typename _Tp, typename _Up> >> + constexpr bool >> + cmp_not_equal(_Tp __t, _Up __u) noexcept >> + { return !std::cmp_equal(__t, __u); } >> + >> + template<typename _Tp, typename _Up> >> + constexpr bool >> + cmp_less(_Tp __t, _Up __u) noexcept >> + { >> + static_assert(__is_standard_integer<_Tp>::value); >> + static_assert(__is_standard_integer<_Up>::value); >> + >> + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) >> + return __t < __u; >> + else if constexpr (is_signed_v<_Tp>) >> + return __t < 0 || make_unsigned_t<_Tp>(__t) < __u; >> + else >> + return __u >= 0 && __t < make_unsigned_t<_Up>(__u); >> + } >> + >> + template<typename _Tp, typename _Up> >> + constexpr bool >> + cmp_greater(_Tp __t, _Up __u) noexcept >> + { return std::cmp_less(__u, __t); } >> + >> + template<typename _Tp, typename _Up> >> + constexpr bool >> + cmp_less_equal(_Tp __t, _Up __u) noexcept >> + { return !std::cmp_less(__u, __t); } >> + >> + template<typename _Tp, typename _Up> >> + constexpr bool >> + cmp_greater_equal(_Tp __t, _Up __u) noexcept >> + { return !std::cmp_less(__t, __u); } >> + >> + template<typename _Res, typename _Tp> >> + constexpr bool >> + in_range(_Tp __t) noexcept >> + { >> + static_assert(__is_standard_integer<_Res>::value); >> + static_assert(__is_standard_integer<_Tp>::value); >> + using __gnu_cxx::__int_traits; >> + >> + if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>) >> + return __int_traits<_Res>::__min <= __t >> + && __t <= __int_traits<_Res>::__max; >> + else if constexpr (is_signed_v<_Tp>) >> + return __t >= 0 >> + && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max; >> + else >> + return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max); >> + } >> + >> +_GLIBCXX_END_NAMESPACE_VERSION >> +} // namespace >> + >> +#endif // __glibcxx_integer_comparison_functions >> +#endif // _GLIBCXX_INTCMP_H >> diff --git a/libstdc++-v3/include/std/latch >> b/libstdc++-v3/include/std/latch >> index 9504df0a7224..df126c6a9ec9 100644 >> --- a/libstdc++-v3/include/std/latch >> +++ b/libstdc++-v3/include/std/latch >> @@ -41,7 +41,7 @@ >> #ifdef __cpp_lib_latch // C++ >= 20 && atomic_wait >> #include <bits/atomic_base.h> >> #include <ext/numeric_traits.h> >> -#include <utility> // cmp_equal, cmp_less_equal, etc. >> +#include <bits/intcmp.h> // cmp_equal, cmp_less_equal, etc. >> >> namespace std _GLIBCXX_VISIBILITY(default) >> { >> diff --git a/libstdc++-v3/include/std/utility >> b/libstdc++-v3/include/std/utility >> index 3ae1852426e8..0f6dd82b1a78 100644 >> --- a/libstdc++-v3/include/std/utility >> +++ b/libstdc++-v3/include/std/utility >> @@ -78,7 +78,7 @@ >> #include <bits/utility.h> >> >> #if __cplusplus >= 202002L >> -#include <ext/numeric_traits.h> // __is_standard_integer, __int_traits >> +#include <bits/intcmp.h> >> #endif >> >> #if __cplusplus > 202302L >> @@ -129,76 +129,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> void as_const(const _Tp&&) = delete; >> #endif >> >> -#ifdef __cpp_lib_integer_comparison_functions // C++ >= 20 >> - template<typename _Tp, typename _Up> >> - constexpr bool >> - cmp_equal(_Tp __t, _Up __u) noexcept >> - { >> - static_assert(__is_standard_integer<_Tp>::value); >> - static_assert(__is_standard_integer<_Up>::value); >> - >> - if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) >> - return __t == __u; >> - else if constexpr (is_signed_v<_Tp>) >> - return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u; >> - else >> - return __u >= 0 && __t == make_unsigned_t<_Up>(__u); >> - } >> - >> - template<typename _Tp, typename _Up> >> - constexpr bool >> - cmp_not_equal(_Tp __t, _Up __u) noexcept >> - { return !std::cmp_equal(__t, __u); } >> - >> - template<typename _Tp, typename _Up> >> - constexpr bool >> - cmp_less(_Tp __t, _Up __u) noexcept >> - { >> - static_assert(__is_standard_integer<_Tp>::value); >> - static_assert(__is_standard_integer<_Up>::value); >> - >> - if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) >> - return __t < __u; >> - else if constexpr (is_signed_v<_Tp>) >> - return __t < 0 || make_unsigned_t<_Tp>(__t) < __u; >> - else >> - return __u >= 0 && __t < make_unsigned_t<_Up>(__u); >> - } >> - >> - template<typename _Tp, typename _Up> >> - constexpr bool >> - cmp_greater(_Tp __t, _Up __u) noexcept >> - { return std::cmp_less(__u, __t); } >> - >> - template<typename _Tp, typename _Up> >> - constexpr bool >> - cmp_less_equal(_Tp __t, _Up __u) noexcept >> - { return !std::cmp_less(__u, __t); } >> - >> - template<typename _Tp, typename _Up> >> - constexpr bool >> - cmp_greater_equal(_Tp __t, _Up __u) noexcept >> - { return !std::cmp_less(__t, __u); } >> - >> - template<typename _Res, typename _Tp> >> - constexpr bool >> - in_range(_Tp __t) noexcept >> - { >> - static_assert(__is_standard_integer<_Res>::value); >> - static_assert(__is_standard_integer<_Tp>::value); >> - using __gnu_cxx::__int_traits; >> - >> - if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>) >> - return __int_traits<_Res>::__min <= __t >> - && __t <= __int_traits<_Res>::__max; >> - else if constexpr (is_signed_v<_Tp>) >> - return __t >= 0 >> - && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max; >> - else >> - return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max); >> - } >> -#endif // __cpp_lib_integer_comparison_functions >> - >> #ifdef __cpp_lib_to_underlying // C++ >= 23 >> /// Convert an object of enumeration type to its underlying type. >> template<typename _Tp> >> -- >> 2.52.0 >> >>
