2

我有一个简单的MyElement类,我想使用 abool MyElement::SomeMethod(...) {...}作为项目的自定义比较std::setMyElement

我已经进行了研究,并且已经知道了一些替代解决方案,我在下面列出了这些解决方案。我也知道如何更改,例如,比较器用std::greater而不是默认值std::less,代码如下:

std::set<MyElement, std::greater<MyElement> > s;

我的确切问题是我想bool MyElement::SomeMethod(...) {...}用作自定义比较器。我想出的唯一解决方案类似于下面列表中的最后一个,即布尔函数的解决方案:

using Cmp = std::integral_constant<decltype(&MyElement::SomeMethod), 
                                   &MyElement::SomeMethod>;
std::set<MyElement, Cmp> my_set;

但是,此解决方案仅适用于 a static MyElement::SomeMethod

我想知道非静态方法是否有类似的或更简洁的方法。

替代解决方案列表:

C++20 的方法

auto cmp = [](const MyElement& lhs, const MyElement& rhs) { return ... };
std::set<MyElement, decltype(cmp)> s;

C++11 的方法

auto cmp = [](const MyElement& lhs, const MyElement& rhs) { return ... };
std::set<MyElement, decltype(cmp)> s(cmp);

函数而不是 lambda

 bool cmp(const MyElement& lhs, const MyElement& rhs) { return ...; }

接着

std::set<MyElement, decltype(cmp)*> s(cmp);

或者

std::set<int, decltype(&cmp)> s(&cmp);

结构和运算符()

struct cmp {
    bool operator() (const MyElement& lhs, const MyElement& rhs) const {
        return ...
    }
};

接着

std::set<MyElement, cmp> s;

布尔函数

bool cmp(const MyElement& lhs, const MyElement& rhs) {
    return ...;
}

接着

#include <type_traits>
using Cmp = std::integral_constant<decltype(&cmp), &cmp>;
std::set<MyElement, Cmp> s;
4

2 回答 2

2

这有点主观,但对我来说,最简洁的选择是 struct + operator() 来匹配 的定义std::less,即std::set. 其他选项没有任何问题,但比较函子是一种常见模式并且易于识别。

您也可以定义MyElement::operator<,然后您不需要单独传入比较器。

于 2021-12-29T21:54:19.890 回答
1

您可以使用std::mem_fn绑定成员函数。

#include <functional>
#include <iostream>
#include <set>
#include <utility>

struct S {
  int i;

  bool cmp(const S& other) const { return i < other.i; }
};

// Define make function to avoid having to write out template types.
template <typename T, typename Cmp>
std::set<T, Cmp> make_set(Cmp&& cmp) {
  return std::set<T, Cmp>{std::forward<Cmp>(cmp)};
}

int main(int argc, char* argv[]) {
  auto s = make_set<S>(std::mem_fn(&S::cmp));
  s.emplace(S{0});

  std::cout << s.begin()->i << std::endl;
  return 0;
}
于 2021-12-29T22:38:13.900 回答