You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为C++20枚举类重载<=>飞船运算符?

枚举类重载C++20<=>飞船运算符不生效的问题解决

问题根源

你的代码里两个核心问题导致自定义比较逻辑没生效:

  1. <=>返回类型不符合规范:C++20要求三路比较运算符operator<=>必须返回标准比较范畴类型(比如std::strong_ordering、std::weak_ordering),而不是int。返回int的重载无法被编译器识别为合法的三路比较实现,因此编译器会直接使用强枚举类默认生成的关系运算符——也就是直接比较底层uint8_t的值。
  2. 默认运算符的优先级:强枚举类带底层类型时,编译器会自动生成默认的operator<=>和关系运算符(</>/<=/>=)。当你的自定义operator<=>不符合规范时,编译器会忽略它,继续使用默认实现。

另外,你尝试删除默认关系运算符的操作无效,是因为删除后编译器无法从你的int返回值的<=>生成替代的关系运算符,最终还是会 fallback 到底层类型的比较逻辑;显式调用<=>出现歧义,则是因为你的自定义版本和默认生成的版本同时存在,编译器无法选择。

解决方案

只要修正operator<=>的返回类型,并实现正确的比较逻辑,就能让自定义规则生效,同时完全不会干扰uint8_t自身的运算符。

修正后的代码

#include <cstdio>
#include <compare>
#include <cstdint>
#include <unordered_map>

enum class Animals : uint8_t
{
  Bird = 27,
  Tiger = 5,
  Ant = 100,
  Snake = 45,
  Wale = 17
};

// 定义动物的实际大小顺序:Ant < Bird < Snake < Tiger < Wale
const std::unordered_map<Animals, int> size_rank = {
    {Animals::Ant, 0},
    {Animals::Bird, 1},
    {Animals::Snake, 2},
    {Animals::Tiger, 3},
    {Animals::Wale, 4}
};

// 返回标准比较范畴类型std::strong_ordering
std::strong_ordering operator<=>(Animals lhs, Animals rhs)
{
    std::cout << "comparing via overloaded <=> operator\n";
    // 用预定义的顺序值进行比较
    return size_rank.at(lhs) <=> size_rank.at(rhs);
}

int main(void)
{
  if(Animals::Ant < Animals::Tiger)
    std::puts("success (do I see the prompt of the overloaded operator?)");
  else
    std::puts("seems to use uint8_t comparison instead");

  // 额外测试其他比较逻辑
  if(Animals::Wale > Animals::Tiger)
    std::puts("Wale is bigger than Tiger, correct");
  
  return 0;
}

关键说明

  • 返回类型修正:使用std::strong_ordering作为返回值,符合C++20的三路比较规范,编译器会自动基于这个<=>生成所有关系运算符(</>/<=/>=),无需手动定义。
  • 自定义逻辑实现:通过映射表将枚举值映射到实际大小的顺序值,避免了大量的if-else判断,逻辑更清晰且易于维护。
  • 无干扰uint8_t:重载仅针对Animals枚举类型,完全不会影响uint8_t自身的任何运算符行为。

运行修正后的代码,会看到输出自定义的提示信息,且Animals::Ant < Animals::Tiger会返回true,符合实际大小顺序。

内容的提问来源于stack exchange,提问作者Tom Mekken

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 05:00:54