std::set 的 MyElement,MyElement::SomeMethod 作为自定义比较器
std::set of MyElement with MyElement::SomeMethod as custom comparator
我有一个简单的 MyElement
class,我想使用 bool MyElement::SomeMethod(...) {...}
作为 std::set
个 MyElement
项的自定义比较器.
我已经进行了研究,并且已经知道一些替代解决方案,我在下面列出了这些解决方案。
我也知道如何更改,例如,使用 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;
不过,此解决方案仅适用于 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;
这有点主观,但对我来说最干净的选择是 struct + operator() 来匹配 std::less
的定义,std::set
的默认比较器。其他选项没有任何问题,但比较函子是一种常见的模式并且很容易识别。
你也可以定义MyElement::operator<
,这样就不需要单独传入比较器了
您可以使用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;
}
我有一个简单的 MyElement
class,我想使用 bool MyElement::SomeMethod(...) {...}
作为 std::set
个 MyElement
项的自定义比较器.
我已经进行了研究,并且已经知道一些替代解决方案,我在下面列出了这些解决方案。
我也知道如何更改,例如,使用 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;
不过,此解决方案仅适用于 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;
这有点主观,但对我来说最干净的选择是 struct + operator() 来匹配 std::less
的定义,std::set
的默认比较器。其他选项没有任何问题,但比较函子是一种常见的模式并且很容易识别。
你也可以定义MyElement::operator<
,这样就不需要单独传入比较器了
您可以使用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;
}