简体   繁体   中英

STL priority_queue parameters

When creating a STL priority_queue, the third argument (the one that decides how to compare elements in the queue to decide which is largest)must be a class in which the function operator is defined. It would be much more convenient if a lambda expression could be supplied. Why is that not allowed? A lambda expression should be considered to be compile time constant if it is not capturing any variables, right?

struct compare{
  bool operator()(int p, int q){return p > q;}
};

priority_queue< int, vector<int>, compare> intpq;

priority_queue< int, vector<int>,
                [](int p, int q){return p > q;}
 > intpq2;

The second definition, ie of intpq2, gives an error: template argument 3 is invalid. Is there a fundamental problem in accepting the second definition, or is it just that the designers of priority_queue chose not to allow it?

The third parameter of std::priority_queue is a type. A lambda expression is not a type, but rather, an expression (you can think of it as an instance or object of something). On top of that, lambdas do not have an type that can be known a priori , but stateless lambdas do convert to pointer to function .

There are some work-arounds you can use in order to instantiate priority_queues with lambdas:

  • Make the 3rd parameter a pointer to function and pass a stateless lambda to the constructor. You can also pass plain function pointers. For example,

  • Make the 3rd parameter an std::function<bool(int, int)> and pass any kind of lambda that matches the correct signature to the constructor. You can pass anything that can be used to construct an std::function<bool(int)> .

For example,

// no capture. Pointer to function is OK
std::priority_queue<int, std::vector<int>, bool (*)(int, int)>
    q2([](int a, int b){return a < b;});

or

// capture. Can't use pointer to function.
std::priority_queue<int, std::vector<int>, std::function<bool(int, int)>>
    q2([some_var](int a, int b){return a < b;});

The third template parameter of priority_queue is a type. Lambda expressions are, well, expressions , not types. An expression has a type. Each lambda expression has a distinct, "unspeakable", type. Pretty much the only way you can refer to it is via auto and decltype :

auto cmp = [](int a, int b){return a < b;};
std::priority_queue<int, std::vector<int>, decltype(cmp)> q1(cmp);

Which is OK if you are just using q1 locally. If you need to pass it around, it can be rather difficult for the users of your function to spell the priority_queue 's type, and you may need to resort to one of the ways shown in @juanchopanza's answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM