将 std::real 作为投影传递给 ranges::sort 不会编译

Passing std::real to ranges::sort as a projection doesn't compile

提问人:Horst Kretschmer 提问时间:9/5/2023 更新时间:9/5/2023 访问量:74

问:

我正在尝试通过传递 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++ C++20 投影 复数 标准范围

评论

0赞 Jarod42 9/5/2023
在实践中,有几个过载,所以是模棱两可的。std::real<T>&std::real<T>
1赞 Jarod42 9/5/2023
迂腐地不是一个可寻址的功能std::real
0赞 BoP 9/5/2023
“丑陋”有多丑?您不必单独创建 lambda,但可以这样做ranges::sort(P, {}, [](cp a) { return real(a); });

答:

0赞 康桓瑋 9/5/2023 #1

一个类似的问题,按大小对向量的向量进行排序,编译和 完美工作。

但是,这是未指定的行为,除非标准指定它是可寻址函数,否则不允许直接获取标准库函数的地址。

在 C++20 中,更简单的方法是将自定义点对象作为投影:ranges::size

ranges::sort(tst, {}, ranges::size);

对于这种情况,使用 lambda 是最合适的选择。但是您可以使用宏来简化代码,例如:std::complex

#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));