Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Defining priority_queue objects

50 views
Skip to first unread message

Paul

unread,
Oct 8, 2018, 6:07:40 PM10/8/18
to
The below code contains a definition
std::priority_queue<int, std::vector<int>, std::greater<int> > q2;

and another definition
std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);

I don't understand why these definitions have different forms?
I would expect either
std::priority_queue<int, std::vector<int>, std::greater<int> > q2;
std::priority_queue<int, std::vector<int>, decltype(cmp)> q3;

or
std::priority_queue<int, std::vector<int>, std::greater<int> > q2(std::greater<int>);
std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);

As written, there doesn't seem to be consistent syntax between the two
definitions.

Thank you,

Paul


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

template<typename T> void print_queue(T& q) {
while(!q.empty()) {
std::cout << q.top() << " ";
q.pop();
}
std::cout << '\n';
}

int main() {
std::priority_queue<int> q;

for(int n : {1,8,5,6,3,4,0,9,7,2})
q.push(n);

print_queue(q);

std::priority_queue<int, std::vector<int>, std::greater<int> > q2;

for(int n : {1,8,5,6,3,4,0,9,7,2})
q2.push(n);

print_queue(q2);

// Using lambda to compare elements.
auto cmp = [](int left, int right) { return (left ^ 1) < (right ^ 1);};
std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);

for(int n : {1,8,5,6,3,4,0,9,7,2})
q3.push(n);

print_queue(q3);

}

Öö Tiib

unread,
Oct 8, 2018, 6:23:52 PM10/8/18
to
On Tuesday, 9 October 2018 01:07:40 UTC+3, Paul wrote:
> The below code contains a definition
> std::priority_queue<int, std::vector<int>, std::greater<int> > q2;
>
> and another definition
> std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);
>
> I don't understand why these definitions have different forms?
> I would expect either
> std::priority_queue<int, std::vector<int>, std::greater<int> > q2;
> std::priority_queue<int, std::vector<int>, decltype(cmp)> q3;
>
> or
> std::priority_queue<int, std::vector<int>, std::greater<int> > q2(std::greater<int>);
> std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);
>
> As written, there doesn't seem to be consistent syntax between the two
> definitions.
>
> Thank you,
>
> Paul


The standard library is not made for your idea of symmetry and beauty but
for usefulness.

Default-constructed std::greater<int> does compare two ints so that
constructor argument may be omitted. Default-constructed lambda with
two int patrameters that returns bool however does not make sense,
so there you must pass actual lambda of that type to priority
queue's constructor.

Pavel

unread,
Oct 8, 2018, 11:41:38 PM10/8/18
to
Öö Tiib wrote:
> On Tuesday, 9 October 2018 01:07:40 UTC+3, Paul wrote:
>> The below code contains a definition
>> std::priority_queue<int, std::vector<int>, std::greater<int> > q2;
>>
>> and another definition
>> std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);
>>
>> I don't understand why these definitions have different forms?
>> I would expect either
>> std::priority_queue<int, std::vector<int>, std::greater<int> > q2;
>> std::priority_queue<int, std::vector<int>, decltype(cmp)> q3;
>>
>> or
>> std::priority_queue<int, std::vector<int>, std::greater<int> > q2(std::greater<int>);
>> std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);
>>
>> As written, there doesn't seem to be consistent syntax between the two
>> definitions.
>>
>> Thank you,
>>
>> Paul
>
>
> The standard library is not made for your idea of symmetry and beauty but
> for usefulness.
>
> Default-constructed std::greater<int> does compare two ints so that
> constructor argument may be omitted. Default-constructed lambda with
> two int patrameters that returns bool however does not make sense,
Why? Lambda is by and large syntactic sugar for an old-fashion function object
that can perfectly default constructor regardless of the operator()'s parameter
and return types.

> so there you must pass actual lambda of that type to priority
> queue's constructor.

I think it's not standard library's but language's restriction. I hear it is
going to be relaxed in C++ 20 so that

std::priority_queue<int, std::vector<int>, decltype(cmp)> q3;

will become legal.

-Pavel

Öö Tiib

unread,
Oct 9, 2018, 3:17:47 AM10/9/18
to
On general case we can make run-time values and references to be
part of object not its type. Lambdas may capture those.
So lambda is of unspecified type that is not required to be
default-constructive.

>
> > so there you must pass actual lambda of that type to priority
> > queue's constructor.
>
> I think it's not standard library's but language's restriction. I hear it is
> going to be relaxed in C++ 20 so that
>
> std::priority_queue<int, std::vector<int>, decltype(cmp)> q3;
>
> will become legal.

There you may be correct of course. The paragraphs and diagnostics
about lambda and its capture can be likely never confusing enough
for franchised tastes.

Pavel

unread,
Oct 9, 2018, 11:03:14 PM10/9/18
to
Well, when there are captures, the default constructor's semantics is, indeed,
unclear.

When there is no capture as in OP question, I feel that the opposite is true:
anything but trivial default constructor is unnatural. The original (?) proposal
can be read here:
http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0624r0.pdf and the
motivation is pretty much same as the OP's, namely the consistency with function
object construction.

I can see it's included in 8.4.5-12 of n4750 draft.

-Pavel

Öö Tiib

unread,
Oct 10, 2018, 12:27:21 PM10/10/18
to
On Wednesday, 10 October 2018 06:03:14 UTC+3, Pavel wrote:
> Öö Tiib wrote:
> >
> > On general case we can make run-time values and references to be
> > part of object not its type. Lambdas may capture those.
> > So lambda is of unspecified type that is not required to be
> > default-constructive.
> Well, when there are captures, the default constructor's semantics is, indeed,
> unclear.
>
> When there is no capture as in OP question, I feel that the opposite is true:
> anything but trivial default constructor is unnatural. The original (?) proposal
> can be read here:
> http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0624r0.pdf and the
> motivation is pretty much same as the OP's, namely the consistency with function
> object construction.
>
> I can see it's included in 8.4.5-12 of n4750 draft.

Thanks for the link. The idea basically lets us to have code in
template argument list like that:

std::set<std::string, decltype([](auto x, auto y) {return x > y;})> map;

Some will hate to see it but ... matter of taste. Also there will be
a question in stackoverflow over a week asking to explain strange
diagnostics when they try same with lambda that captures something.
And after fix is suggested they will ask same question like OP of
this thread.

0 new messages