关于使用位操作涉及位的模式的建议

Suggestion for a pattern involving bits using bit manipulation

我目前有这样的结构

struct foo
{
  UINT64 optionA = 0;
  UINT64 optionB = 0;
  UINT64 optionC = 0;
}

我正在尝试编写一个函数,用于根据 optionAoptionBoptionC 比较 foo 的两个对象。本质上我希望函数做的是检查 optionA 是否相同,如果没有,则 return 返回最低的对象。如果两个对象中的 optionA 相同,那么它将检查两个对象中的 optionB 并且 return 最低的一个。如果 optionB 两者相同,那么它将查看 optionC 和 return 最低的。

我认为这可以通过为每个对象分配一个 UINT64 编号来实现。 然后根据优先级为那个 no 分配位,然后比较每个位和 return 返回较小的位。我不确定如何采用这种方法,如有任何建议,我们将不胜感激。

该代码目前缺少检查相等性的运算符。

示例:

constexpr bool operator==(const foo& a, const foo& b) {
    return
        a.optionA == b.optionA &&
        a.optionB == b.optionB &&
        a.optionC == b.optionC;
}

这样,下面的代码将编译(有意义):

using UINT64 = /* unsigned long long */; // usually

struct foo {
    UINT64 optionA = 0;
    UINT64 optionB = 0;
    UINT64 optionC = 0;
};

constexpr bool operator==(const foo& a, const foo& b) {
    return
        a.optionA == b.optionA &&
        a.optionB == b.optionB &&
        a.optionC == b.optionC;
}

int main() {
    constexpr foo a, b;
    static_assert(a == b);
}

对于 C++20,default operator <=>operator == 就可以完成这项工作。

struct foo
{
  UINT64 optionA = 0;
  UINT64 optionB = 0;
  UINT64 optionC = 0;

  auto operator <=>(const foo&) const = default;
  bool operator ==(const foo&) const = default;
};

否则,std::tuple 可能会有所帮助:

bool operator ==(const foo& lhs, const foo& rhs)
{
   return std::tie(lhs.optionA, lhs.optionB, lhs.optionC)
       == std::tie(rhs.optionA, rhs.optionB, rhs.optionC);
}

bool operator <(const foo& lhs, const foo& rhs)
{
   return std::tie(lhs.optionA, lhs.optionB, lhs.optionC)
        < std::tie(rhs.optionA, rhs.optionB, rhs.optionC);
}

如果有一个比较函数以正确的顺序直接比较数据成员会更简单和更易读,但是如果有存储哪些数据成员更大的位掩码出于其他原因有帮助,那么这里是我会怎么做:

foo compare(foo x, foo y)
{
    // needs to hold status for 3 data members (one bit each)
    int x_status = 0, y_status = 0;

    // each bit is 1 if this member is bigger, 0 if smaller
    x_status |= (x.optionC > y.optionC)<<0;
    x_status |= (x.optionB > y.optionB)<<1;
    x_status |= (x.optionA > y.optionA)<<2;

    // each bit is 1 if this member is bigger, 0 if smaller
    y_status |= (x.optionC < y.optionC)<<0;
    y_status |= (x.optionB < y.optionB)<<1;
    y_status |= (x.optionA < y.optionA)<<2;

    // so now we can compare the values
    // if all the data members were bigger the value will be 7 (0b111)
    // if all the data members were smaller the value will be 0 (0b000)
    if (x_status < y_status) return x; else return y;
}

在此处在线试用:https://onlinegdb.com/XpdOSFLFa