https://gcc.gnu.org/g:0ea9d760fbf44c6f50c50a4e259d3ef2c756606c
commit r16-5624-g0ea9d760fbf44c6f50c50a4e259d3ef2c756606c Author: Tomasz Kamiński <[email protected]> Date: Thu Nov 20 11:23:30 2025 +0100 libstdc++: Make C++20s operator wrappers operator() static. The operator() for function objects introduced in C++20 (e.g., std::identity, std::compare_three_way, std::ranges::equal) is now defined as static. Although static operator() is a C++23 feature, it is supported in C++20 by both GCC and clang (since their support was added in clang-16). This change is not user-observable, as all affected operators are template functions. Taking the address of such an operator requires casting to a pointer to member function with a specific signature. The exact signature is unspecified per C++20 [member.functions] p2 (e.g. due to potential parameters with default arguments). libstdc++-v3/ChangeLog: * include/bits/ranges_cmp.h (std::identity::operator()): (ranges::equal_to:operator(), ranges::not_equal_to:operator()) (ranges::greater::operator(), ranges::greater_equal::operator()) (ranges::less::operator(), ranges::less_equal::operator()): Declare as static. * libsupc++/compare (std::compare_three_way::operator()): Declare as static. Reviewed-by: Jonathan Wakely <[email protected]> Reviewed-by: Patrick Palka <[email protected]> Signed-off-by: Tomasz Kamiński <[email protected]> Diff: --- libstdc++-v3/include/bits/ranges_cmp.h | 34 ++++++++++++++++++++-------------- libstdc++-v3/libsupc++/compare | 7 +++++-- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/libstdc++-v3/include/bits/ranges_cmp.h b/libstdc++-v3/include/bits/ranges_cmp.h index cd5f7b8b37a2..a53cd5645635 100644 --- a/libstdc++-v3/include/bits/ranges_cmp.h +++ b/libstdc++-v3/include/bits/ranges_cmp.h @@ -46,11 +46,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// [func.identity] The identity function. struct identity { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++23-extensions" // static operator() template<typename _Tp> [[nodiscard]] - constexpr _Tp&& - operator()(_Tp&& __t) const noexcept + static constexpr _Tp&& + operator()(_Tp&& __t) noexcept { return std::forward<_Tp>(__t); } +#pragma GCC diagnostic pop using is_transparent = __is_transparent; }; @@ -79,13 +82,15 @@ namespace ranges // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3530 BUILTIN-PTR-MEOW should not opt the type out of syntactic checks +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++23-extensions" // static operator() /// ranges::equal_to function object type. struct equal_to { template<typename _Tp, typename _Up> requires equality_comparable_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>())) { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); } @@ -97,8 +102,8 @@ namespace ranges { template<typename _Tp, typename _Up> requires equality_comparable_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>())) { return !equal_to{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } @@ -110,8 +115,8 @@ namespace ranges { template<typename _Tp, typename _Up> requires totally_ordered_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) { if constexpr (__detail::__less_builtin_ptr_cmp<_Tp, _Up>) @@ -137,8 +142,8 @@ namespace ranges { template<typename _Tp, typename _Up> requires totally_ordered_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) { return less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } @@ -150,8 +155,8 @@ namespace ranges { template<typename _Tp, typename _Up> requires totally_ordered_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) { return !less{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } @@ -163,13 +168,14 @@ namespace ranges { template<typename _Tp, typename _Up> requires totally_ordered_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) { return !less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } using is_transparent = __is_transparent; }; +#pragma GCC diagnostic pop } // namespace ranges #endif // __glibcxx_ranges diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare index 458b47c3fcab..08f2b2ba47ed 100644 --- a/libstdc++-v3/libsupc++/compare +++ b/libstdc++-v3/libsupc++/compare @@ -573,10 +573,12 @@ namespace std _GLIBCXX_VISIBILITY(default) // [cmp.object], typename compare_three_way struct compare_three_way { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++23-extensions" // static operator() template<typename _Tp, typename _Up> requires three_way_comparable_with<_Tp, _Up> - constexpr auto - operator() [[nodiscard]] (_Tp&& __t, _Up&& __u) const + static constexpr auto + operator() [[nodiscard]] (_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Tp>() <=> std::declval<_Up>())) { if constexpr (__detail::__3way_builtin_ptr_cmp<_Tp, _Up>) @@ -592,6 +594,7 @@ namespace std _GLIBCXX_VISIBILITY(default) else return static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u); } +#pragma GCC diagnostic pop using is_transparent = void; };
