lambda 与 priority_queue 以及 function 以及 bind
Posted 远近闻名的学渣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lambda 与 priority_queue 以及 function 以及 bind相关的知识,希望对你有一定的参考价值。
lambda是一种可调用对象,它是一个对象,每个lambda都有自己不同的类型。
年轻时以为STL和lambda混用时会有一些奇怪现象,比如我无法像这样定义优先队列:
priority_queue<int, vector<int>, [](int a, int b) {return a > b;}> que;
但是却可以这样用sort
sort (vec.begin(), vec.end(), [](int a, int b) {return a < b;});
以及可以这样用sort
bool less(int a, int b) { return a < b;} typedef bool (*cmp) (int, int); cmp mycmp = less; sort (vec.begin(), vec.end(), mycmp); sort (vec.begin(), vec.end(), less);
之所以会出现这样的疑问,是因为没有搞清楚函数对象 (也叫可调用对象) 和 模板的类型参数之间的关系, 首先说明如何正确的使用 lambda 对象来实例化priority_queue :
#include <iostream> #include <queue> #include <vector> #include <utility> using my_pair_t = std::pair<size_t,bool>; using my_container_t = std::vector<my_pair_t>; int main() { auto my_comp = [](const my_pair_t& e1, const my_pair_t& e2) { return e1.first > e2.first; }; std::priority_queue<my_pair_t, my_container_t, decltype(my_comp)> queue(my_comp); queue.push(std::make_pair(5, true)); queue.push(std::make_pair(3, false)); queue.push(std::make_pair(7, true)); std::cout << std::boolalpha; while(!queue.empty()) { const auto& p = queue.top(); std::cout << p.first << " " << p.second << "\n"; queue.pop(); } }
1, 首先这里的my_comp是一个对象,由于每个lambda对象都有一个匿名的类型,所以只能用auto来表达my_comp的类型
2, 优先队列的声明是这样的:
template< class T, class Container = std::vector<T>, class Compare = std::less<typename Container::value_type> > class priority_queue;
所以要实例化一个优先队列,尖括号里得填typename啊, 由于 lambda 对象的类型是匿名的,所以用decltype搞定,再然后光这样是不行的,这会来看构造函数:
explicit priority_queue( const Compare& compare = Compare(), const Container& cont = Container() );
可以看到,如果我们构造时,不指定特定的compare对象,那么就用typename Compare的默认构造函数构造一个,然而lambda表达式的匿名类型是没有默认构造函数的,
所以想要正确初始化这个优先队列,还得在构造函数里再把lambda表达式本身传进去
3, 函数指针,函数, lambda表达式,函数对象之间的关系
首先看sort的一个重载声明:
template <class RandomAccessIterator, class Compare> void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
这里sort接受一个函数对象,所以直接给传递lambda对象是可以的,因为lambda对象属于函数对象嘛,在C++里凡是能够使用函数调用运算符的,都是函数对象,所以
函数对象有: 函数, 函数指针, 重载了()的类的对象,以及lambda对象。
注意,函数和函数指针是两个不同的东西,就像虽然数组在作为参数时会被当成指针传递,但是他们依旧不是同一个东西,即:
虽然在非引用时,数组和函数都会被转换成指针(包括模板参数推断也会这样),但是他们仍旧不是指针,指针的例子不用多说,举个函数的例子:
template <typename T> void t(const T& t) { cout << std::is_pointer<T>::value << endl; t(); } template <typename T> void e(T t) { cout << std::is_pointer<T>::value << endl; t(); } void f() { } int main() { t(f); cout << endl; e(f); return 0; }
第一次调用输出的是0,第二次则是1,这也就是说函数本身 和 函数指针也是两个东西
至此也就解释了一开始说到的如何使用sort以及priority_queue的原因了
以上是关于lambda 与 priority_queue 以及 function 以及 bind的主要内容,如果未能解决你的问题,请参考以下文章
C++ std::priority_queue 使用 lambda 表达式
c++优先级队列priority_queue使用lambda表达式出错问题
c++优先级队列priority_queue使用lambda表达式出错问题