抱歉标题太长,正如我所说,这是有效的:
struct S { int a{}, b{}; };
std::ostream &operator<<(std::ostream &o, const S &s) { return o << '{' << s.a << ',' << s.b << '}'; }
template <auto ptr>
bool f(const S &a, const S &b)
{
return a.*ptr < b.*ptr;
}
int main()
{
std::vector<S> v{{1,9},{2,8},{3,7},{4,6},{6,4},{7,3},{8,2},{9,1}};
std::sort(v.begin(), v.end(), f<&S::b>);
// Sort by S::b -----> ^^^^^
for (const auto &s : v)
std::cout << s << ' ';
// output: {9,1} {8,2} {7,3} {6,4} {4,6} {3,7} {2,8} {1,9}
return 0;
}
但这不是:
…
auto l = []<auto ptr>(const S &a, const S &b)
{
return a.*ptr < b.*ptr;
};
std::sort(v.begin(), v.end(), l<&S::b>);
// Sort by S::b? -----> ^^^^^
…
这是错误:
error: no match for 'operator<' (operand types are 'main()::<lambda(const S&, const S&)>' and 'int S::*')
std::sort(v.begin(), v.end(), l<&S::b>);
~^~~~~~
看起来 lambda 的模板符号作为
std::sort
的参数被视为 l
小于 (<
) &S::b>
的比较,这不是我的意图。
我应该如何将模板 lambda 传递给
std::sort
函数?
你可以这样做:
std::ranges::sort(v, {}, &S::b)
。
您的版本不起作用,因为
l
不是模板。它是一个带有模板化 operator()
的类实例。
&decltype(l)::operator()<&S::b>
可以编译,但是生成的成员指针不是 std::sort
可以使用的。
如果您使用 lambda
static
([](...) static {...}
,C++23 功能),或者将该表达式包装在 std::bind_front(..., l)
或等效项中,它将起作用。
老实说,如果您出于某种原因不想使用
std::ranges::sort()
,我会忘记模板并执行以下操作:
auto l = [](auto ptr)
{
return [ptr](const S &a, const S &b)
{
return a.*ptr < b.*ptr;
};
};
std::sort(v.begin(), v.end(), l(&S::b));