The implementation of less<> did not consider the possibility of t < u being
rewritten from overloaded operator<=>. This lead to situation when for t,u that:
* provide overload operator<=>, such that (t < u) is rewritten to (t <=> u) < 0,
* are convertible to pointers,
the expression std::less<>(t, u) would incorrectly result in call of
std::less<void*> on values converted to the pointers, instead of t < u.
The similar issues also occurred for greater<>, less_equal<>, greater_equal<>,
their range equivalents, and in three_way_compare for heterogeneous calls.
This patch addresses above, by also checking for free-functions and member
overloads of operator<=>, before falling back to pointer comparison. We do
not put any constraints on the return type of selected operator, in particular
in being one of the standard defined comparison categories, as the language
does not put any restriction of returned type, and if (t <=> u) is well
formed, (t op u) is interpreted as (t <=> u) op 0. If that later expression
is ill-formed, the expression using op also is (see included tests).
The relational operator rewrites try both order of arguments, t < u,
can be rewritten into operator<=>(t, u) < 0 or 0 < operator<=>(u, t), it
means that we need to test both operator<=>(T, U) and operator<=>(U, T)
if T and U are not the same types. This is now extracted into
__not_overloaded_spaceship helper concept, placed in <concepts>, to
avoid extending set of includes.
The compare_three_way functor defined in compare, already considers overloaded
operator<=>, however it does not consider reversed candidates, leading
to situation in which t <=> u results in 0 <=> operator<=>(u, t), while
compare_three_way{}(t, u) uses pointer comparison. This is also addressed by
using __not_overloaded_spaceship, that check both order of arguments.
Finally, as operator<=> is introduced in C++20, for std::less(_equal)?<>,
std::greater(_equal)?<>, we use provide separate __ptr_cmp implementation
in that mode, that relies on use of requires expression. We use a nested
requires clause to guarantee short-circuiting of their evaluation.
The operator() of aforementioned functors is reworked to use if constexpr,
in all standard modes (as we allow is as extension), eliminating the need
for _S_cmp function.
PR libstdc++/114153
libstdc++-v3/ChangeLog:
* include/bits/ranges_cmp.h (__detail::__less_builtin_ptr_cmp):
Add __not_overloaded_spaceship spaceship check.
* include/bits/stl_function.h (greater<void>::operator())
(less<void>::operator(), greater_equal<void>::operator())
(less_equal<void>::operator()): Implement using if constexpr.
(greater<void>::__S_cmp, less<void>::__S_cmp)
(greater_equal<void>::__ptr_comp, less_equal<void>::S_cmp):
Remove.
(greater<void>::__ptr_cmp, less<void>::__ptr_cmp)
(greater_equal<void>::__ptr_comp, less_equal<void>::ptr_cmp): Change
tostatic constexpr variable. Define in terms of requires expressions
and __not_overloaded_spaceship check.
* include/std/concepts: (__detail::__not_overloaded_spaceship):
Define.
* libsupc++/compare: (__detail::__3way_builtin_ptr_cmp): Use
__not_overloaded_spaceship concept.
* testsuite/20_util/function_objects/comparisons_pointer_spaceship.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
This implements the C++23 proposal P2404R3 "Move-only types for
equality_comparable_with, totally_ordered_with, and
three_way_comparable_with". As agreed with the maintainers of libc++ and
MSVC STL, we treat this as a DR for C++20. It allows reasonable code to
compile which wasn't originally allowed in C++20, and only affects some
obscure subsumption cases for valid C++20 code.
libstdc++-v3/ChangeLog:
PR libstdc++/122946
* include/bits/version.def (concepts): Set value to 202207.
* include/bits/version.h: Regenerate.
* include/std/concepts (__comparison_common_type_with_impl)
(__comparison_common_type_with): New helper concepts.
(equality_comparable_with): Use __comparison_common_type_with.
* libsupc++/compare (three_way_comparable_with): Likewise.
(__glibcxx_want_concepts): Define to get __cpp_lib_concepts
here.
* testsuite/std/concepts/concepts.compare/move_only.cc: New
test.
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
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 <jwakely@redhat.com>
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
The approved P3778R0 wording doesn't have type_order<_Tp, _Up>::type, so
this patch removes it.
2025-11-10 Jakub Jelinek <jakub@redhat.com>
* libsupc++/compare: Implement final wording of C++26 P3778R0 - Fix
for type_order template definition.
(std::type_order): Remove type member.
This slightly improve the readability of error message, by suggesting
that 0 (literal) is expected as argument:
invalid conversion from 'int' to 'std::__cmp_cat::__literal_zero*'
libstdc++-v3/ChangeLog:
* libsupc++/compare (__cmp_cat::__literal_zero): Rename
from __unspec.
(__cmp_cat::__unspec): Rename to __literal_zero.
(operator==, operator<, operator>, operator<=, operator>=):
Replace __cmp_cat::__unspec to __cmp_cat::__literal_zero.
This patch adds two new internal helpers for ordering types:
* __cmp_cat::__ord to retrieve an internal _Ord value,
* __cmp_cat::__make<Ordering> to create an ordering from an _Ord value.
Conversions between ordering types are now handled by __cmp_cat::__make. As a
result, ordering types no longer need to befriend each other, only the new
helpers.
The __fp_weak_ordering implementation has also been simplified by:
* using the new helpers to convert partial_ordering to weak_ordering,
* using strong_ordering to weak_ordering conversion operator,
for the __isnan_sign comparison,
* removing the unused __cat local variable.
Finally, the _Ncmp enum is removed, and the unordered enumerator is added
to the existing _Ord enum.
libstdc++-v3/ChangeLog:
* libsupc++/compare (__cmp_cat::_Ord): Add unordered enumerator.
(__cmp_cat::_Ncmp): Remove.
(__cmp_cat::__ord, __cmp_cat::__make): Define.
(partial_ordering::partial_ordering(__cmp_cat::_Ncmp)): Remove.
(operator<=>(__cmp_cat::__unspec, partial_ordering))
(partial_ordering::unordered): Replace _Ncmp with _Ord.
(std::partial_ordering, std::weak_ordering, std::strong_ordering):
Befriend __ord and __make helpers, remove friend declartions for
other orderings.
(__compare::__fp_weak_ordering): Remove unused __cat variable.
Simplify ordering conversions.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
The patch r16-3414-gfcb3009a32dc33 changed the representation of unordered to
optimize reversing of order, but it did not update implementation of reversing
operator<=>(0, partial_order).
libstdc++-v3/ChangeLog:
* libsupc++/compare
(operator<=>(__cmp_cat::__unspec, partial_ordering)):
Implement using _M_reverse.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
For any minimum value of a signed type, its negation (with wraparound) results
in the same value, behaving like zero. Representing the unordered result with
this minimum value, along with 0 for equal, 1 for greater, and -1 for less
in partial_ordering, allows its value to be reversed using unary negation.
The operator<=(partial_order, 0) now checks if the reversed value is positive.
This works correctly because the unordered value remains unchanged and thus
negative.
libstdc++-v3/ChangeLog:
* libsupc++/compare (_Ncmp::_Unordered): Rename and change the value
to minimum value of signed char.
(_Ncomp::unordered): Renamed from _Unordered, the name is reserved
by partial_ordered::unordered.
(partial_ordering::_M_reverse()): Define.
(operator<=(partial_ordering, __cmp_cat::__unspec))
(operator>=(__cmp_cat::__unspec, partial_ordering)): Implemented
in terms of negated _M_value.
(operator>=(partial_ordering, __cmp_cat::__unspec))
(operator<=(__cmp_cat::__unspec, partial_ordering)): Directly
compare _M_value, as unordered value is negative.
(partial_ordering::unordered): Handle _Ncmp::unoredred rename.
* python/libstdcxx/v6/printers.py: Add -128 as integer value
for unordered, keeping 2 to preserve backward compatibility.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
The following patch attempts to implement the C++26 P2830R10 - Constexpr Type
Ordering paper, with a minor change that std::type_order<T, U> class template
doesn't derive from integer_constant, because std::strong_ordering is not
a structural type (except in MSVC), so instead it is just a class template
with static constexpr strong_ordering value member and also value_type,
type and 2 operators.
The paper mostly talks about using something other than mangled names for
the ordering, but given that the mangler is part of the GCC C++ FE, using
the mangler seems to be the best ordering choice to me.
2025-06-26 Jakub Jelinek <jakub@redhat.com>
gcc/cp/
* cp-trait.def: Implement C++26 P2830R10 - Constexpr Type Ordering.
(TYPE_ORDER): New.
* method.cc (type_order_value): Define.
* cp-tree.h (type_order_value): Declare.
* semantics.cc (trait_expr_value): Use gcc_unreachable also
for CPTK_TYPE_ORDER, adjust comment.
(finish_trait_expr): Handle CPTK_TYPE_ORDER.
* constraint.cc (diagnose_trait_expr): Likewise.
gcc/testsuite/
* g++.dg/cpp26/type-order1.C: New test.
* g++.dg/cpp26/type-order2.C: New test.
* g++.dg/cpp26/type-order3.C: New test.
libstdc++-v3/
* include/bits/version.def (type_order): New.
* include/bits/version.h: Regenerate.
* libsupc++/compare: Define __glibcxx_want_type_order before
including bits/version.h.
(std::type_order, std::type_order_v): New trait and template variable.
* src/c++23/std.cc.in (std::type_order, std::type_order_v): Export.
* testsuite/18_support/comparisons/type_order/1.cc: New test.
The use of #pragma GCC system_header in libstdc++ has led to bugs going
undetected for a while due to the silencing of compiler warnings that would
have revealed them promptly, and also interferes with warnings about
problematic template instantiations induced by user code.
But removing it, or even compiling with -Wsystem-header, is also problematic
due to warnings about deliberate uses of extensions.
So this patch adds #pragma GCC diagnostic as needed to suppress these
warnings.
The change to acinclude.m4 changes -Wabi to warn only in comparison to ABI
19, to avoid lots of warnings that we now mangle concept requirements, which
are in any case still experimental. I checked for any other changes against
ABI v15, and found only the <format> lambda mangling, which we can ignore.
This also enables -Wsystem-headers while building the library, so we see any
warnings not silenced by these #pragmas.
libstdc++-v3/ChangeLog:
* include/bits/algorithmfwd.h:
* include/bits/allocator.h:
* include/bits/codecvt.h:
* include/bits/concept_check.h:
* include/bits/cpp_type_traits.h:
* include/bits/hashtable.h:
* include/bits/iterator_concepts.h:
* include/bits/ostream_insert.h:
* include/bits/ranges_base.h:
* include/bits/regex_automaton.h:
* include/bits/std_abs.h:
* include/bits/stl_algo.h:
* include/c_compatibility/fenv.h:
* include/c_compatibility/inttypes.h:
* include/c_compatibility/stdint.h:
* include/ext/concurrence.h:
* include/ext/type_traits.h:
* testsuite/ext/type_traits/add_unsigned_floating_neg.cc:
* testsuite/ext/type_traits/add_unsigned_integer_neg.cc:
* testsuite/ext/type_traits/remove_unsigned_floating_neg.cc:
* testsuite/ext/type_traits/remove_unsigned_integer_neg.cc:
* include/bits/basic_ios.tcc:
* include/bits/basic_string.tcc:
* include/bits/fstream.tcc:
* include/bits/istream.tcc:
* include/bits/locale_classes.tcc:
* include/bits/locale_facets.tcc:
* include/bits/ostream.tcc:
* include/bits/regex_compiler.tcc:
* include/bits/sstream.tcc:
* include/bits/streambuf.tcc:
* configure: Regenerate.
* include/bits/c++config:
* include/c/cassert:
* include/c/cctype:
* include/c/cerrno:
* include/c/cfloat:
* include/c/climits:
* include/c/clocale:
* include/c/cmath:
* include/c/csetjmp:
* include/c/csignal:
* include/c/cstdarg:
* include/c/cstddef:
* include/c/cstdio:
* include/c/cstdlib:
* include/c/cstring:
* include/c/ctime:
* include/c/cwchar:
* include/c/cwctype:
* include/c_global/climits:
* include/c_global/cmath:
* include/c_global/cstddef:
* include/c_global/cstdlib:
* include/decimal/decimal:
* include/ext/rope:
* include/std/any:
* include/std/charconv:
* include/std/complex:
* include/std/coroutine:
* include/std/format:
* include/std/iomanip:
* include/std/limits:
* include/std/numbers:
* include/tr1/functional:
* include/tr1/tuple:
* include/tr1/type_traits:
* libsupc++/compare:
* libsupc++/new: Add #pragma GCC diagnostic to suppress
undesired warnings.
* acinclude.m4: Change -Wabi version from 2 to 19.
gcc/ChangeLog:
* ginclude/stdint-wrap.h: Add #pragma GCC diagnostic to suppress
undesired warnings.
* gsyslimits.h: Likewise.
This implements the C++23 change "Poison Pills are Too Toxic". This
makes sense to do unconditionally for C++20, as the corner cases that it
fixes are considered to be defects in the C++20 design (e.g. LWG3480 was
needed to fix directory iterators because of these pills being too
toxic).
libstdc++-v3/ChangeLog:
* include/bits/iterator_concepts.h (__imove::iter_move): Define
poison pill as deleted for consistency.
(__access::begin): Replace with a single declaration.
* include/bits/ranges_base.h (__access::end, __access::rbegin)
(__access::rend, __access::size): Likewise.
* include/bits/version.def (ranges): Update value for C++23.
* include/bits/version.h: Regenerate.
* libsupc++/compare (__compare): Add missing poison pill
overloads.
* testsuite/std/ranges/version_c++23.cc: Adjust expected value
of __cpp_lib_ranges.
* testsuite/std/ranges/access/p2602.cc: New test.
This makes the naming of the CPO types and namespaces simpler and more
consistent. With this change the string "cust" won't appear in
diagnostics related to these CPOs, which avoids confusion about what it
means (customization? customer?). Users don't really need to care that
these are called "customization point objects", so don't show them the
string "cust". Names like "__imove::_IterMove" are preferable to names
like "__cust_imove::_IMove" as the former is more obviously related to
the public API "ranges::iter_move".
Instead of a plethora of inline namespaces for all the different CPO
objects, define them all in an inline namespace called _Cpo (which isn't
shown to users anyway, unlike the types of those objects).
libstdc++-v3/ChangeLog:
* include/bits/iterator_concepts.h (ranges::__cust_imove):
Rename to ranges::__imove.
(_IMove): Rename to _IterMove.
(ranges::__cust_iswap): Rename to ranges::__iswap.
(ranges::__cust): Rename to ranges::_Cpo.
(ranges::__cust_access): Rename to ranges::__access.
* include/bits/ranges_base.h (ranges::__cust_access): Rename to
ranges::__access.
(ranges::__cust): Rename to ranges::_Cpo.
* include/std/concepts (ranges::__cust_swap): Rename to
ranges::__swap.
(ranges::__cust): Rename to ranges::_Cpo.
* libsupc++/compare (__cmp_cust): Rename to __compare.
(__cmp_algo): Rename to _Cpo.
This constructor should only ever be used with a literal 0 as the
argument, so we can make it consteval. This has the nice advantage that
it is expanded immediately in the front end, and so GDB will never step
into the __cmp_cat::__unseq::__unseq(__unseq*) constructor that is
uninteresting and probably confusing to users.
libstdc++-v3/ChangeLog:
* libsupc++/compare (__cmp_cat::__unseq): Make ctor consteval.
* testsuite/18_support/comparisons/categories/zero_neg.cc: Prune
excess errors caused by invalid consteval calls.
Jon pointed out that we have TODO: _Bfloat16 in <compare>.
Right now _S_fp_fmt() returns _Binary16 for _Float16, __fp16 as well
as __bf16 and it actually works because we don't have a special handling
of _Binary16. So, either we could just document that, but I'm a little bit
afraid if HPPA or MIPS don't start supporting _Float16 and/or __bf16.
If they do, we have the
#if defined __hppa__ || (defined __mips__ && !defined __mips_nan2008)
// IEEE 754-1985 allowed the meaning of the quiet/signaling
// bit to be reversed. Flip that to give desired ordering.
if (__builtin_isnan(__x) && __builtin_isnan(__y))
{
using _Int = decltype(__ix);
constexpr int __nantype = __fmt == _Binary32 ? 22
: __fmt == _Binary64 ? 51
: __fmt == _Binary128 ? 111
: -1;
constexpr _Int __bit = _Int(1) << __nantype;
__ix ^= __bit;
__iy ^= __bit;
}
#endif
code, the only one where we actually care whether something is
_Binary{32,64,128} (elsewhere we just care about the x86 and m68k 80bits
or double double or just floating point type's sizeof) and we'd need
to handle there _Binary16 and/or _Bfloat16.
So this patch uses different enum for it even when it isn't needed right
now, after all _Binary16 isn't needed either and we could just use
_Binary32...
2022-11-02 Jakub Jelinek <jakub@redhat.com>
* libsupc++/compare (_Strong_order::_Fp_fmt): Add _Bfloat16.
(_Strong_order::_Bfloat16): New static data member.
(_Strong_order::_S_fp_fmt): Return _Bfloat16 for std::bfloat16_t.
Once we no longer care about older compilers without this feature, we
can drop these static data members, so the names don't have to be
visible at class scope.
libstdc++-v3/ChangeLog:
* libsupc++/compare (_Strong_order) [!__cpp_using_enum]: Add
static data members for _Fp_fmt enumerators.
I mistakenly believed that VAX floats do not support NaN, but with GCC
__builtin_isnan(__builtin_nan("")) is true. That means my previous
change to <compare> is wrong, because it fails to handle NaN.
When std::numeric_limits<floating-point-type>::is_iec559 is false, as on
VAX, the standard only requires an ordering that is consistent with the
ordering observed by comparison operators. With this change the ordering
is -NaN < numbers < +NaN, and there is no support for different NaN bit
patterns (as I'm not even sure if GCC supports any for VAX).
libstdc++-v3/ChangeLog:
* libsupc++/compare (_Strong_order::_S_fp_cmp) [__vax__]:
Handle NaN.
The VAX float and double format does not support NaN, so the
std::partial_ordering returned by <=> will never be 'unordered'. We can
just use the partial_ordering value as the strong_ordering.
libstdc++-v3/ChangeLog:
* libsupc++/compare (_Strong_ordering::_S_fp_cmp) [__vax__]: Use
<=> comparison.
This removes a FIXME in <compare>, defining the total order for
floating-point types. I originally opened PR96526 to request a new
compiler built-in to implement this, but now that we have std::bit_cast
it can be done entirely in the library.
The implementation is based on the glibc definitions of totalorder,
totalorderf, totalorderl etc.
I think this works for all the types that satisfy std::floating_point
today, and should also work for the types expected to be added by P1467
except for std::bfloat16_t. It also supports some additional types that
don't currently satisfy std::floating_point, such as __float80, but we
probably do want that to satisfy the concept for non-strict modes.
libstdc++-v3/ChangeLog:
PR libstdc++/96526
* libsupc++/compare (strong_order): Add missing support for
floating-point types.
* testsuite/18_support/comparisons/algorithms/strong_order_floats.cc:
New test.
This adds std::__is_constant_evaluated() as a C++11 wrapper for
__builtin_is_constant_evaluated, but just returning false if the
built-in isn't supported by the compiler. This allows us to use it
throughout the library without checking __has_builtin every time.
Some uses in std::vector and std::string can only be constexpr when the
std::is_constant_evaluated() function actually works, so we might as
well guard them with a relevant macro and call that function directly,
rather than the built-in or std::__is_constant_evaluated().
The remaining checks of the __cpp_lib_is_constant_evaluated macro could
now be replaced by checking __cplusplus >= 202002 instead, but there's
no practical difference. We still need some kind of preprocessor check
there anyway.
libstdc++-v3/ChangeLog:
* doc/doxygen/user.cfg.in (PREDEFINED): Change macro name.
* include/bits/allocator.h (allocate, deallocate): Use
std::__is_constant_evaluated() unconditionally, instead of
checking whether std::is_constant_evaluated() (or the built-in)
can be used.
* include/bits/basic_string.h: Check new macro. call
std::is_constant_evaluated() directly in C++20-only code that is
guarded by a suitable macro.
* include/bits/basic_string.tcc: Likewise.
* include/bits/c++config (__is_constant_evaluated): Define.
(_GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED): Replace with ...
(_GLIBCXX_HAVE_IS_CONSTANT_EVALUATED): New macro.
* include/bits/char_traits.h (char_traits): Replace conditional
calls to std::is_constant_evaluated with unconditional calls to
std::__is_constant_evaluated.
* include/bits/cow_string.h: Use new macro.
* include/bits/ranges_algobase.h (__copy_or_move): Replace
conditional calls to std::is_constant_evaluated with unconditional
calls to std::__is_constant_evaluated.
(__copy_or_move_backward, __fill_n_fn): Likewise.
* include/bits/ranges_cmp.h (ranges::less): Likewise.
* include/bits/stl_algobase.h (lexicographical_compare_three_way):
Likewise.
* include/bits/stl_bvector.h: Call std::is_constant_evaluated
directly in C++20-only code that is guarded by a suitable macro.
* include/bits/stl_construct.h (_Construct, _Destroy, _Destroy_n):
Replace is_constant_evaluated with __is_constant_evaluated.
* include/bits/stl_function.h (greater, less, greater_equal)
(less_equal): Replace __builtin_is_constant_evaluated and
__builtin_constant_p with __is_constant_evaluated.
* include/bits/stl_vector.h: Call std::is_constant_evaluated()
in C++20-only code.
* include/debug/helper_functions.h (__check_singular): Use
__is_constant_evaluated instead of built-in, or remove check
entirely.
* include/std/array (operator<=>): Use __is_constant_evaluated
unconditionally.
* include/std/bit (__bit_ceil): Likewise.
* include/std/type_traits (is_constant_evaluated): Define using
'if consteval' if possible.
* include/std/version: Use new macro.
* libsupc++/compare: Use __is_constant_evaluated instead of
__builtin_is_constant_evaluated.
* testsuite/23_containers/array/tuple_interface/get_neg.cc:
Adjust dg-error lines.
This adds the [[nodiscard]] attribute to all conversion operators,
comparison operators, call operators and non-member functions in
<compare>. Nothing in this header except constructors has side effects.
Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:
* libsupc++/compare (partial_ordering, weak_ordering)
(strong_ordering, is_eq, is_neq, is_lt, is_lteq, is_gt, is_gteq)
(compare_three_way, strong_order, weak_order, partial_order)
(compare_strong_order_fallback, compare_weak_order_fallback)
(compare_partial_order_fallback, __detail::__synth3way): Add
nodiscard attribute.
* testsuite/18_support/comparisons/categories/zero_neg.cc: Add
-Wno-unused-result to options.
This moves the same_as<decay_t<_Tp>, decay_t<_Up>> checks from the
[cmp.alg] function bodies into their constraints.
Also add a test for the compare_xxx_order_fallback algorithms.
libstdc++-v3/ChangeLog:
* libsupc++/compare (__decayed_same_as): New helper concept.
(strong_order, weak_order, partial_order): Constrain with new
concept instead of using static_assert.
(compare_strong_order_fallback, compare_weak_order_fallback)
(compare_partial_order_fallback): Likewise. Do not deduce return
types. Remove redundant if-constexpr checks.
* testsuite/18_support/comparisons/algorithms/fallback.cc: New test.
The proposed resolution for this library issue simplifies the
constraints for compare_three_way, ranges::equal_to, ranges::less etc.
so that they do not work with types which are convertible to pointers
but which fail to meet the usual syntactic requirements for the
comparisons.
This affects the example in PR libstdc++/93628 but doesn't fix the
problem described in that report.
libstdc++-v3/ChangeLog:
* include/bits/ranges_cmp.h (__eq_builtin_ptr_cmp): Remove.
(ranges::equal_to, ranges::not_equal_to): Do not constrain
with __eq_builtin_ptr_cmp.
(ranges::less, ranges::greater, ranges::less_equal)
(ranges::greater_equal): Do not constrain with
__less_builtin_ptr_cmp.
* libsupc++/compare (compare_three_way): Do not constrain with
__3way_builtin_ptr_cmp.
* testsuite/18_support/comparisons/object/builtin-ptr-three-way.cc: Moved to...
* testsuite/18_support/comparisons/object/lwg3530.cc: ...here.
* testsuite/20_util/function_objects/range.cmp/lwg3530.cc: New test.
With P1614R2 fully implemented (except for the <chrono> types which we
don't support at all) we can define the feature test macro to the new
value.
* include/std/version (__cpp_lib_three_way_comparison): Update value.
* libsupc++/compare (__cpp_lib_three_way_comparison): Likewise.
My "simplification" of std::compare_three_way's constraints in commit
f214ffb336 was incorrect, because
std::three_way_comparable_with imposes additional restrictions beyond
the <=> expression being valid.
* libsupc++/compare (compare_three_way): Fix constraint so that
BUILTIN-PTR-THREE-WAY does not require three_way_comparable_with.
* testsuite/18_support/comparisons/object/builtin-ptr-three-way.cc:
New test.
LWG 3324 changed the [cmp.alg] types to use std::compare_three_way
instead of the <=> operator, but we were still using the old
specification. In order to make the existing tests pass the N::X type
needs to be equality comparable, so that three_way_comparable is
satisfied and compare_three_way can be used.
As part of this change I noticed that the compare_three_way call
operator was unconditionally noexcept, which is incorrect.
* libsupc++/compare (compare_three_way): Fix noexcept-specifier.
(strong_order, weak_order, partial_order): Replace uses of <=> with
compare_three_way function object (LWG 3324).
* testsuite/18_support/comparisons/algorithms/partial_order.cc: Add
equality operator so that X satisfies three_way_comparable.
* testsuite/18_support/comparisons/algorithms/strong_order.cc:
Likewise.
* testsuite/18_support/comparisons/algorithms/weak_order.cc: Likewise.
This also removes a useless condition that was supposed to be removed by
the P1959R0 changes, but left in when that was implemented.
* libsupc++/compare (three_way_comparable): Remove always-false check
that should have been removed with weak_equality (P1959R0).
(three_way_comparable_with): Likewise. Reorder requirements (LWG 3360).
* include/std/concepts (__detail::__partially_ordered_with): Move here
from <compare>.
(totally_ordered, totally_ordered_with): Use __partially_ordered_with
to simplify definition (LWG 3331).
* libsupc++/compare (__detail::__partially_ordered_with): Move to
<concepts>.
This removes the complicated std::boolean concept, as agreed in Prague.
* include/bits/ranges_algo.h (__find_fn, __find_first_of_fn)
(__adjacent_find_fn): Cast result of predicate to bool.
* include/std/concepts (__boolean): Remove.
(__detail::__boolean_testable_impl, __detail::__boolean_testable): Add
new helper concepts.
(__detail::__weakly_eq_cmp_with, totally_ordered, totally_ordered_with)
(predicate): Use __boolean_testable instead of boolean.
* libsupc++/compare (__detail::__partially_ordered, _Synth3way):
Likewise.
This reduces the size and alignment of all three comparison category
types to a single byte. The partial_ordering::_M_is_ordered flag is
replaced by the value 0x02 in the _M_value member.
This also optimizes conversion and comparison operators to avoid
conditional branches where possible, by comparing _M_value to constants
or using bitwise operations to correctly handle the unordered state.
* libsupc++/compare (__cmp_cat::type): Define typedef for underlying
type of enumerations and comparison category types.
(__cmp_cat::_Ord, __cmp_cat::_Ncmp): Add underlying type.
(__cmp_cat::_Ncmp::unordered): Change value to 2.
(partial_ordering::_M_value, weak_ordering::_M_value)
(strong_ordering::_M_value): Change type to __cmp_cat::type.
(partial_ordering::_M_is_ordered): Remove data member.
(partial_ordering): Use second bit of _M_value for unordered. Adjust
comparison operators.
(weak_ordering::operator partial_ordering): Simplify to remove
branches.
(operator<=>(unspecified, weak_ordering)): Likewise.
(strong_ordering::operator partial_ordering): Likewise.
(strong_ordering::operator weak_ordering): Likewise.
(operator<=>(unspecified, strong_ordering)): Likewise.
* testsuite/18_support/comparisons/categories/partialord.cc: New test.
* testsuite/18_support/comparisons/categories/strongord.cc: New test.
* testsuite/18_support/comparisons/categories/weakord.cc: New test.
The __3way_builtin_ptr_cmp concept can use three_way_comparable_with to
check whether <=> is valid. Doing that makes it obvious that the
disjunction on compare_three_way::operator() is redundant, because
the second constraint subsumes the first.
The workaround for PR c++/91073 can also be removed as that bug is fixed
now.
* libsupc++/compare (__detail::__3way_builtin_ptr_cmp): Use
three_way_comparable_with.
(__detail::__3way_cmp_with): Remove workaround for fixed bug.
(compare_three_way::operator()): Remove redundant constraint from
requires-clause.
(__detail::_Synth3way::operator()): Use three_way_comparable_with
instead of workaround.
* testsuite/18_support/comparisons/object/93479.cc: Prune extra
output due to simplified constraints on compare_three_way::operator().
Currently types that cannot be compared using <=> but which are
convertible to pointers will be compared by converting to pointers
first. They should not be comparable.
PR libstdc++/93479
* libsupc++/compare (__3way_builtin_ptr_cmp): Require <=> to be valid.
* testsuite/18_support/comparisons/object/93479.cc: New test.
The _Eq and _Ord enumerations can be combined into one, reducing the
number of constructors needed for the comparison category types. The
redundant equal enumerator can be removed and equivalent used in its
place. The _Less and _Greater enumerators can be renamed because 'less'
and 'greater' are already reserved names anyway.
* libsupc++/compare (__cmp_cat::_Eq): Remove enumeration type.
(__cmp_cat::_Ord::equivalent): Add enumerator.
(__cmp_cat::_Ord::_Less, __cmp_cat::_Ord::_Greater): Rename to less
and greater.
(partial_ordering, weak_ordering, strong_ordering): Remove
constructors taking __cmp_cat::_Eq parameters. Use renamed
enumerators.
The contents of the <compare> header are not complete unless concepts
are supported, so the feature test macro should depend on the macro for
concepts.
As a result, the std::lexicographical_compare_three_way function will
not be defined unless concepts are supported, so there is no need to
check __cpp_lib_concepts before using concepts in those functions.
* include/bits/stl_algobase.h (__is_byte_iter, __min_cmp)
(lexicographical_compare_three_way): Do not depend on
__cpp_lib_concepts.
* include/std/version (__cpp_lib_three_way_comparison): Only define
when __cpp_lib_concepts is defined.
* libsupc++/compare (__cpp_lib_three_way_comparison): Likewise.
From-SVN: r279896
* libsupc++/compare (common_comparison_category): Define without using
concepts and optimise for compilation time.
(__detail::__cmp_cat_ids): Remove.
(__detail::__common_cmp_cat): Replace class template and
specializations with constexpr function.
From-SVN: r279307
This defines operator<=> as a non-member function template and does not
alter operator==. This contradicts the changes made by P1614R2, which
specify both as hidden friends, but that specification of operator<=> is
broken and the subject of a soon-to-be-published LWG issue.
* include/bits/stl_pair.h [__cpp_lib_three_way_comparison]
(operator<=>): Define for C++20.
* libsupc++/compare (__cmp2way_res_t): Rename to __cmp3way_res_t,
move into __detail namespace. Do not turn argument types into lvalues.
(__cmp3way_helper): Rename to __cmp3way_res_impl, move into __detail
namespace. Constrain with concepts instead of using void_t.
(compare_three_way_result): Adjust name of base class.
(compare_three_way_result_t): Use __cmp3way_res_impl directly.
(__detail::__3way_cmp_with): Add workaround for PR 91073.
(compare_three_way): Use workaround.
(__detail::__synth3way, __detail::__synth3way_t): Define new helpers
implementing synth-three-way and synth-three-way-result semantics.
* testsuite/20_util/pair/comparison_operators/constexpr_c++20.cc: New
test.
From-SVN: r278951