繁体   English   中英

为枚举 class 覆盖 c++20 飞船运算符

[英]overwrite c++20 spaceship operator for enum class

我正在努力为枚举 class 提供新的宇宙飞船操作员。让我们举以下例子:

#include <cstdio>
#include <iostream>
#include <compare>
#include <cstdint>

enum class Animals : uint8_t
{
  Bird = 27, //those values are just for making a point
  Tiger = 5,
  Ant = 100,
  Snake = 45,
  Wale = 17
};

//auto operator<=(const Animals& lhs, const Animals& rhs) = delete;
//auto operator>=(const Animals& lhs, const Animals& rhs) = delete;
//auto operator<(const Animals& lhs, const Animals& rhs) = delete;
//auto operator>(const Animals& lhs, const Animals& rhs) = delete;

auto operator<=>(const Animals& lhs, const Animals& rhs)
{
    std::cout << "comparing via overloaded <=> operator\n";
  //order the animals by their size in real life
  // Ant < Bird < Snake < Tiger < Wale
  //for this MVCE only Ant < Tiger is in here:
  if(lhs == Animals::Ant && rhs == Animals::Tiger)
    return -1;
  return 0; //all unimplemented ones are treated as equal
}

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");

  return 0;
  
}

但很明显我在这里弄错了,因为我的main()仍然告诉我,蚂蚁比老虎大。 如您所见,我试图显式删除默认的比较运算符,以强制编译器使用我的自定义太空船一号,但没有成功。

当我显式调用auto result = Animals::Ant <=> Animals::Tiger时,我得到了ambiguous overload for 'operator<=>' (operand types are 'Animals' and 'Animals') 但这似乎与我的操作员签名有关(改为使用const Animals)。

是否可以覆盖我的枚举的运算符(而不干扰其基本类型“uint8_t”的运算符?

您的operator<=>有两个问题:

  1. 它需要按值而不是按常量引用来获取枚举,以抑制内置候选
  2. 它需要返回比较类别之一,而不是int 在这种情况下,可能std::weak_ordering是正确的。

那是:

constexpr auto operator<=>(Animals lhs, Animals rhs) -> std::weak_ordering
{
  //order the animals by their size in real life
  // Ant < Bird < Snake < Tiger < Wale
  //for this MVCE only Ant < Tiger is in here:
  if(lhs == Animals::Ant && rhs == Animals::Tiger)
    return std::weak_ordering::less;
  return std::weak_ordering::equivalent;
}

也就是说,在如何使用<=>处理重写候选者方面存在实现分歧。 clang 和 msvc 实现了规则可能应该是什么,即我们的用户声明的operator<=>抑制了所有内置的关系和三路 comaprison 运算符,以便Animals::Ant < Animals::Tiger调用我们的operator<=> 但是 gcc 实现了规则在技术上实际上字面上所说的,即Animals::Ant <=> Animals::Tiger评估我们的运算符,但使用<不会。 有一个 gcc 错误报告为此打开 ( #105200 ),其中一位 gcc 开发人员指出了措辞问题。 这让我觉得这是一个措辞问题,而不是实际的设计意图问题,所以我要打开一个关于这个的核心问题 ( #205 )。

为了让它在 gcc 上工作,你还必须通过 go 并自己添加这些(注意:总是按值):

constexpr auto operator<(Animals lhs, Animals rhs) -> bool {
    return (lhs <=> rhs) < 0;
}

constexpr auto operator<=(Animals lhs, Animals rhs) -> bool {
    return (lhs <=> rhs) <= 0;
}

constexpr auto operator>(Animals lhs, Animals rhs) -> bool {
    return (lhs <=> rhs) > 0;
}

constexpr auto operator>=(Animals lhs, Animals rhs) -> bool {
    return (lhs <=> rhs) >= 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM