Tenho um caso em que o tipo struct não precisa ser padrão operator<=>
- só que nem todos os campos são importantes ao definir a ordem dos objetos.
struct A
{
int a;
int b; // not important when ordering
int c;
constexpr std::strong_ordering operator<=>(const A& rhs) const
{
if (const auto res = a<=>rhs.a; res != 0) return res;
return c<=>rhs.c;
}
};
Para minha surpresa, não posso usar container com esse tipo como argumento para std::ranges::sort
:
std::array<A, 100> aa{};
std::ranges::sort(aa);
Eu verifiquei no mais novo gcc (14) e clang (19) e ele basicamente afirma que o intervalo não é classificável porque std::invocable_v<std::ranges::less&, A&, A&>
não é verdade. Veja o link godbold
Mais observações:
- Funciona com std::sort(
std::sort(aa.begin(), aa.end());
) - Funciona ao adicionar não padrão
operator==
- E funciona com o padrão (
=default
)operator<=>
Isso é um bug do compilador, um bug padrão do C++ ou alguma regra estranha do C++ está em jogo aqui e deveria ser assim? Se a última opção estiver correta - você pode fornecer uma justificativa para tal comportamento?
Atualizar:
Pelos comentários parece que std::ranges::less{}(A{}, A{})
requer não apenas operator<
(derivado de operator<=>
), mas também operator==
que não pode ser derivado de não padrão, operator<=>
então o erro.
Mas uma questão permanece: por que std::ranges::less
as necessidades operator==
?
E melhor exemplo dos comentários: link