C++11:如何使用 lambda 作为类型参数,它需要像 std::less/std::greater 这样的“函子类型”?

Tro*_*yvs 0 c++ lambda types functor c++11

我试图将类型参数传递给priority_queue,就像 std::less 或 std::greater 一样,如下所示:

priority_queue<int, vector<int>, [](int x, int y){return x>y;})> q;
Run Code Online (Sandbox Code Playgroud)

它无法编译,然后我添加了decltype,仍然失败:

priority_queue<int, vector<int>, decltype([](int x, int y){return x>y;}))> q;
Run Code Online (Sandbox Code Playgroud)

问题是,在这种情况下我们可以使用lambda吗?如何实现呢?

Pen*_*eng 5

有多种方式:

  1. 让编译器使用 推导 lamabda 的类型decltype(lambda)。但您需要记住一件事:在 C++20 之前,lambda 类型没有默认构造函数。从 C++20 开始,只有无状态 lambda(不带捕获的 lambda)具有默认构造函数,而有状态 lambda(即带捕获的 lambda)没有默认构造函数(这在 cppreference.com 上有明确记录)。为什么默认构造函数在这里很重要?答案是,如果存在默认构造函数,则只要将 lambda 类型指定为模板参数,就不必将比较函数 (cmp) 传递给priority_queue 构造函数。由于默认构造函数仅适用于从 C++20 开始的无状态 lambda,因此您最好将 cmp 参数显式传递给构造函数:
auto cmp = [](int x, int y){return x>y;}; 
priority_queue<int, vector<int>, decltype(cmp)> q(cmp);
Run Code Online (Sandbox Code Playgroud)
  1. 使用<functional>标头显式指定 lambda 类型:
#include <functional>
...
priority_queue<int, vector<int>, function<bool(int, int)>> q(cmp);
Run Code Online (Sandbox Code Playgroud)
  1. 使用函数对象类。在这种情况下,您只需将函数对象类指定为模板类型参数,并且不需要将 cmp 参数传递给构造函数,因为您自己定义的函数对象类有一个默认(合成的)构造函数。
struct Cmp {
    bool operator()(int x, int y) {return x > y;}
};
priority_queue<int, vector<int>, Cmp> q;
Run Code Online (Sandbox Code Playgroud)
  1. 尽可能使用库定义的函数对象。
priority_queue<int, vector<int>, std::greater<int>> q;
Run Code Online (Sandbox Code Playgroud)