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; } | ~~~~~~~~~~^~~~~~~~~~~~