我试图通过传递 std::real 作为投影参数来按实数分量对复数向量进行排序,但该参数无法编译。我似乎不明白为什么,主要是因为编译错误非常详细。
使用 lambda 可以,但是很丑,我宁愿不这样做。类似的问题,按大小对向量向量进行排序,可以完美编译和运行。这是我尝试过的:
#include <bits/stdc++.h>
using namespace std;
typedef complex<double> cp;
int main() {
vector<cp> P = {{2, 3}, {12, 30}, {40, 50}, {5, 1}, {12, 10}, {3, 4.2}};
ranges::sort(P, {}, real<double>); // doesn't compile
ranges::sort(P, {}, real<cp>); // doesn't compile
ranges::sort(P, {}, &cp::real); // doesn't compile
auto pj = [](cp a) {return real(a);};
ranges::sort(P, {}, pj); // compiles and works, but is ugly
vector<vector<int>> tst = {{1, 3}, {1, 4, 5}, {1}};
ranges::sort(tst, {}, size<vector<int>>); // compiles and works
ranges::sort(tst, {}, &vector<int>::size); // compiles and works
auto tstpj = [](vector<int>& a) {return size(a);};
ranges::sort(tst, {}, tstpj); // compiles and works, but is ugly
}
为什么复数版本不起作用,如何修复?
类似的问题,按大小对向量的向量进行排序,编译并 完美运作。
但是,这是未定义的行为,不允许直接获取标准库函数的地址,除非标准指定它是一个可寻址函数。
在C++20中,更简单的方法是采用自定义点对象
ranges::size
作为投影:
ranges::sort(tst, {}, ranges::size);
对于
std::complex
的情况,使用lambda仍然是最合适的选择。但你可以用宏来简化代码,例如:
#define MEMBER_FUN(memer_fun) \
[](auto&& x) -> decltype(auto) { return std::forward<decltype(x)>(x).memer_fun(); }
然后你可以更简洁地创建一个 lambda
vector<complex<double>> P = /* */;
ranges::sort(P, {}, MEMBER_FUN(real));
vector<vector<int>> tst = /* */;
ranges::sort(tst, {}, MEMBER_FUN(size));