【问题标题】:specialize std::greater via std::rel_ops通过 std::rel_ops 专门化 std::greater
【发布时间】:2015-10-16 18:11:18
【问题描述】:

如何使用std::rel_ops 专门化std::greater? 我有这样的东西

#include <utility>
#include <functional>

using namespace std::rel_ops;

struct MyStruct {
    int field;
    bool operator < (const MyStruct& rhs) const {
        return field < rhs.field;
    }
};

所以我需要按降序对元素进行排序。我如何使用operator &lt;std::rel_opsstd::greater 来做到这一点?

【问题讨论】:

    标签: c++ compare std


    【解决方案1】:

    我假设您尝试做类似的事情

    MyStruct ms[] = {{10}, {50}, {30}, {20}};
    std::sort(std::begin(ms), std::end(ms), std::greater<MyStruct>{});
    

    编译失败,因为找不到合适的operator&gt;。这是因为std::greater 依赖ADL 来查找运算符重载,并且ADL 在关联的命名空间中进行搜索。 std::rel_ops 不是 MyStruct 的关联命名空间。您可以通过将 using 声明添加到与 MyStruct 相同的命名空间来使一切正常工作,以便找到相关的 operator&gt;

    using std::rel_ops::operator>;
    

    Live demo

    但这很丑陋,一般来说不是一个可行的解决方案,所以忘记std::rel_ops 并将Boost.Operators 用作Barry suggests

    【讨论】:

    • 你为什么觉得它丑?它做的正是它应该做的。
    • @Surt 当然,这是一个见仁见智的问题,但是如果您还想要其他相等运算符,那么您需要 4 个 using 声明。使用 Boost.Operators,您只需从 boost::totally_ordered 派生(在为您的类型定义 operator== 之后)。
    • 我喜欢您的解决方案,因为它不需要包含第三方。
    【解决方案2】:

    你必须这样做:

    std::vector<MyStruct> v{...};
    
    std::sort(v.begin(), v.end(), [](const MyStruct& lhs, const MyStruct& rhs){
        using namespace std::rel_ops;
        return lhs > rhs;
    });
    

    虽然std::rel_ops 很蹩脚。使用boost::less_than_comparable 更简单,只需将运算符直接添加到MyStruct

    struct MyStruct 
        : boost::less_than_comparable<MyStruct> // <== adds operator>,
                                                //          operator>=, 
                                                //      and operator<=
    {
        MyStruct(int i) : field(i) { }
        int field;
    
        bool operator<(const MyStruct& rhs) const {
            return field < rhs.field;
        }
    };
    

    然后你可以用明显的方式对其进行排序:

    std::sort(v.begin(), v.end(), std::greater<MyStruct>());
    

    【讨论】:

      【解决方案3】:

      std::rel_ops 从==&lt; 生成其他比较,因此您首先需要至少定义&lt;

      bool operator<(const MyStruct & lhs, const MyStruct & rhs) {
          return lhs.field < rhs.field;
      }
      

      现在 rel_ops 生成 &gt;,所以现在您可以在 std::sort 中使用 std::greater

      std::sort(begin(myVector), end(myVector), std::greater<MyStruct>());
      

      【讨论】:

      • 我已经定义了运算符
      • 您的&lt; 只有一个参数,而std::greater 需要两个参数,而且您的是std::greater 无法访问的类成员。
      • 不需要非会员operator&lt;,OP定义的会员版本就足够了。问题在于 ADL 没有找到在 namespace rel_ops 中定义的 operator&gt;
      • @Praetorian,是的,我可以从你的回答中看出这一点:) 现在我想知道为什么。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      • 2012-10-10
      • 1970-01-01
      • 2012-09-08
      相关资源
      最近更新 更多