https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98836
Bug ID: 98836
Summary: tie with spaceship requires operator==
Product: gcc
Version: 11.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: nunoplopes at sapo dot pt
Target Milestone: ---
The following program doesn't compile with gcc trunk:
https://gcc.godbolt.org/z/PGqMGn
```
#include <compare>
#include <map>
using namespace std;
struct expr {
strong_ordering operator<=>(const expr &rhs) const;
};
class FunctionExpr {
std::map<expr, expr> fn;
public:
auto operator<=>(const FunctionExpr &rhs) const = default;
};
weak_ordering f(FunctionExpr &a, FunctionExpr &b) {
return tie(a) <=> tie(b);
// <----- the one below is OK
return a <=> b;
}
```
TL;DR: the synthesized <=> operator for std::map calls operator== rather than
just calling operator<=>. The code above works fine with clang.
Error:
include/c++/11.0.0/bits/stl_map.h:1465:23: required from 'bool
std::operator==(const std::map<_Key, _Tp, _Compare, _Allocator>&, const
std::map<_Key, _Tp, _Compare, _Allocator>&) [with _Key = expr; _Tp = expr;
_Compare = std::less<expr>; _Alloc = std::allocator<std::pair<const expr, expr>
>]'
<source>:14:8: required from 'static constexpr bool
std::__detail::_Synth3way::_S_noexcept(const _Tp*, const _Up*) [with _Tp =
FunctionExpr; _Up = FunctionExpr]'
include/c++/11.0.0/compare:885:32: required from 'constexpr auto
std::__detail::_Synth3way::operator()(const _Tp&, const _Up&) const requires
requires{{std::__detail::_Synth3way::operator()::__t <
std::__detail::_Synth3way::operator()::__u} -> decltype(auto) [requires
std::__detail::__boolean_testable<<placeholder>,
>];{std::__detail::_Synth3way::operator()::__u <
std::__detail::_Synth3way::operator()::__t} -> decltype(auto) [requires
std::__detail::__boolean_testable<<placeholder>, >];} [with _Tp = FunctionExpr;
_Up = FunctionExpr]'
include/c++/11.0.0/compare:909:34: required by substitution of
'template<class _Tp, class _Up> using __synth3way_t = decltype
(std::__detail::__synth3way(declval<_Tp&>(), declval<_Up&>())) [with _Tp =
FunctionExpr&; _Up = FunctionExpr&]'
include/c++/11.0.0/tuple:1509:5: required by substitution of 'template<class
... _Tps, class ... _Ups> constexpr
std::common_comparison_category_t<std::__detail::__synth3way_t<_Tps, _Ups>...>
std::operator<=>(const std::tuple<_Tps ...>&, const std::tuple<_Args2 ...>&)
[with _Tps = {FunctionExpr&}; _Ups = {FunctionExpr&}]'
<source>:18:26: required from here
include/c++/11.0.0/bits/stl_pair.h:467:24: error: no match for 'operator=='
(operand types are 'const expr' and 'const expr')
467 | { return __x.first == __y.first && __x.second == __y.second; }
| ~~~~~~~~~~^~~~~~~~~~~~