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

Reply via email to