Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ std::priority_queue uses the lambda expression

Tags:

c++

c++11

lambda

There is statement that the compiler can't pass. I can't understand it. Can anyone tell me in detail or How to fix it ? Best wishes to you.

The statement as follow:

    std::priority_queue<int,std::vector<int>,[](const int& lhs,const int& rhs)
    { 
        return lhs<rhs;
    } > pq;

The compiler given the information as follow:

 type/value mismatch at argument 3 in template parameter list for 
'template<class _Tp, class _Sequence, class _Compare> class std::priority_queue'

The std::priority_queue inducted in cppreference site:http://en.cppreference.com/w/cpp/container/priority_queue

mainly structure as follow:

template<
    class T,
    class Container = std::vector<T>,
    class Compare = std::less<typename Container::value_type>
> class priority_queue;
like image 717
Andy Cong Avatar asked Dec 06 '22 16:12

Andy Cong


1 Answers

The declaration you show has a value, namely a lambda, as actual template argument where the formal template argument (parameter) is a type.


Here is an example of using a type as template argument:

#include <vector>
#include <queue>

auto main()
    -> int
{
    struct My_less
    {
        auto operator()( int const a, int const b ) const
            -> bool
        { return a < b; }
    };

    std::priority_queue< int, std::vector<int>, My_less > pq;
}

Example of using a lambda expression as comparator:

#include <vector>
#include <queue>

auto main()
    -> int
{
    std::priority_queue< int, std::vector<int>, auto(*)(int,int)->bool > pq{
        []( int a, int b )->bool { return a < b; }
        };
}

C++11 §5.1.12/19 says “The closure type associated with a lambda-expression has a deleted (8.4.3) default constructor and a deleted copy assignment operator.”. That means that the type of a lambda expression can not be used to instantiate the lambda from scratch. And the lambda does not convert implicitly to std::less<T> that's expected, which means you cannot use it directly as constructor argument either (and anyway std::less is stateless). But you can specify a comparator type that the lambda does convert to, and then use the lambda as constructor argument. In the above code that comparator type is a simple raw function pointer.


In practice, it is useful to define the lambda functions elsewhere and pass them to the target function as function pointers

#include <vector>
#include <functional>
#include <queue>

void foo(std::function<bool(int &a, int &b)> comparison)
{
    std::priority_queue< int, std::vector<int>, decltype(comparison)> pq {
        comparison
    };
}
auto main()
    -> int
{
    auto comparison = [](int,int)->bool {
        return a < b; 
    }

    foo(Comparison);
}
like image 147
Cheers and hth. - Alf Avatar answered Jan 01 '23 19:01

Cheers and hth. - Alf