如何在多变量结构的“<”实现中不迷路

How not to get lost in implementation of '<' for multi-variable structures

Preferred implementation of '<' for multi-variable structures 类似,我正在为具有多个值的结构实现小于运算符。我不担心使用相等或小于运算符,让我们假设所有成员都正确地实现了这两者。我的结构有四个字段,运算符已经变得很乱了:

struct Key {
    std::string s_name;
    bool b_mipmaps;
    bool b_clamp_to_edge;
    GLenum n_intformat;

    // [constructors here]

    bool operator <(const Key &other) const
    {
        return s_name < other.s_name || (s_name == other.s_name && (
            b_mipmaps < other.b_mipmaps || (b_mipmaps == other.b_mipmaps && (
            b_clamp_to_edge < other.b_clamp_to_edge || (b_clamp_to_edge == other.b_clamp_to_edge && (
            n_intformat < other.n_intformat))))));
        // compare two keys
    }
}

我想知道是否有一种常用的缩进样式或可以帮助您不迷失在括号中的东西,因为坦率地说,这是地狱,我想这样的运算符中的错误会非常微妙和困难追踪/调试。有没有办法将其分解为一些原始功能?或者是否有执行此操作的 STL 函数?

我目前使用的是 C++03,但我对更新的标准持开放态度。

您可以使用多个 if

bool operator <(const Key &other) const
{
    if (s_name != other.s_name) return s_name < other.s_name;
    if (!b_mipmaps && other.b_mipmaps) return true;
    if (b_mipmaps && !other.b_mipmaps) return false;
    if (!b_clamp_to_edge && other.b_clamp_to_edge) return true;
    if (b_clamp_to_edge && !other.b_clamp_to_edge) return false;
    return n_intformat < other.n_intformat;
    // compare two keys
}

不知道你的代码中变量的类型是什么,我发现很难用你的变量名来提出建议。

从你的代码来看,如果

,运算符的语义应该是什么不清楚

(this->b_mipmaps && other.b_mipmaps)true

我使用以下模式:

bool operator <(const Key &other) const
{
   if ( this->member1 != other.member1 )
   {
      return (this->member1 < other.member1);
   }

   if ( this->member2 != other.member2 )
   {
      return (this->member2 < other.member2);
   }

   //
   // ...
   //

   return (this->memberN < other.memberN);
}

编辑

现在我知道 b_mipmapsbool 类型,您可以使用:

   if ( this->b_mipmaps != other.b_mipmaps )
   {
      return (this->b_mipmaps < other.b_mipmaps);
   }

   if ( this->b_mipmaps != other.b_mipmaps )
   {
      return (!(this->b_mipmaps) && other.b_mipmaps);
   }

选择您认为更具可读性的样式。我发现第一种形式更具可读性。

您可以使用 std::tie

bool operator <(const Key &other) const
{
    return std::tie(s_name, b_mipmaps, b_clamp_to_edge, n_intformat) <
        std::tie(other.s_name, other.b_mipmaps, other.b_clamp_to_edge, other.n_intformat);
}

别忘了#include <tuple>

至于@lisyarus 很好的答案,但避免了字段名称的重复:

bool operator <(const Key &other) const
{
    auto fields = [](decltype(*this) v) {
        return std::tie(v.s_name, v.b_mipmaps, v.b_clamp_to_edge, v.n_intformat);
    };
    return (fields(*this) < fields(rhs));
}