0

I am trying to understand the priority queue in stl. What I have understood is that the third argument is basically typename(in this case function pointer). So,if it just accepts the typename, how will it have access over my compare function when it will implement its operations if it just accept typename and not actual function pointer?

#include <iostream>
    #include <bits/stdc++.h>
    using namespace std;
    bool comp(int a,int b){
        return a<b;
    }

    int main()
    {
        int (*p)(int,int);
        p=comp;
        priority_queue< int,vector<int>,decltype(&comp) > pq;
        decltype(p) a;
        cout<<typeid(a).name();
    }
shiwang
  • 150
  • 1
  • 13
  • In this case, it won't. Check out its [constructor](http://en.cppreference.com/w/cpp/container/priority_queue/priority_queue), the priority queue takes an optional comparator of the chosen type. When it's something like `std::less`, a default constructed object is fine, but with a function pointer you'll have to explicitly specify which function you want to use or you'll soon have problems. – Caninonos Feb 13 '18 at 11:11
  • 1
    Please read why [you should not get in the habit of including `bits/stdc++.h`](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) nor [`using namespace std;`](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice). – StoryTeller - Unslander Monica Feb 13 '18 at 11:12
  • @Caninonos So, do I have to send like this? `priority_queue< int,vector,decltype(p) > pq(comp);` But, when I tried to send argument as functor, I don't need to explicitly send the function, Why? – shiwang Feb 13 '18 at 11:25
  • You also don't need `p`. Simply specifying `decltype(comp) *` should do it. – StoryTeller - Unslander Monica Feb 13 '18 at 11:29
  • 1
    Yup. Well, of course, you could also give it a custom allocator, custom underlying container etc... if you wanted. But that's enough to construct a priority queue which won't cause undefined behaviour later. (btw, have you tried using it with and without specifying the comparison function that way ? you should quickly see the difference) – Caninonos Feb 13 '18 at 11:30
  • But, when I tried to send argument as a functor, I don't need explicitly send the function. Why? @Caninonos – shiwang Feb 13 '18 at 11:50
  • Ok, So basically while sending functor I am sending non-type parameter to the template. – shiwang Feb 13 '18 at 12:13
  • You can create the queue like that: `priority_queue< int,vector,decltype(&comp) > pq(p)`, this will initialize the comparator, without the need for a constructor. – user9335240 Feb 13 '18 at 12:26
  • @ShiwangGupta It's not really that you pass a "non-type parameter to the template". In fact, think about it this way : types can be seen as sets of possible values (in an "abstract" and "theoretical" way). `signed char` for instance can be seen as {-127, -126, ..., 127, 128}. Now, the default comparator type is `std::less`, the thing is, this is a stateless object which means the set represented by this type is {std::less()}, it contains only a single value. So if you default construct the comparator, you get the only possible value representable by this type and there's no ambiguity. – Caninonos Feb 13 '18 at 13:29
  • In fact, to better describe this, you could think of types (again theoretically) as a pair (set of possible values, nullary function which picks you an arbitrary element of that set) and the default constructor is that nullary function. When that default element happens to represent something usable (as in std::less' case) you don't have to specify anything, but for pointers to functions, that nullary function gives something that can't be dereferenced reliably. – Caninonos Feb 13 '18 at 13:33
  • Thanks, I get it.. So, that means there are different templates defined depending on the way what I send as third parameter. – shiwang Feb 13 '18 at 14:47

1 Answers1

0

So,if it just accepts the typename, how will it have access over my compare function when it will implement its operations if it just accept typename and not actual function pointer?

There are two options for you.

  1. Make a class, that can be constructed which has this function as a call operator.

    struct comparator {
        bool operator()(int a, int b) { return comp(a, b); }
    };
    

    Then use like you written, pass only the typename:

    priority_queue< int,vector<int>,comparator > pq;
    
  2. Pass a reference to your object (which may be a function pointer). So no need for constructing your object again:

    priority_queue< int,vector<int>,decltype(p) > pq(p)
    

    Where p is the function pointer you made before.

    bool (*p)(int,int);
    p=comp;
    priority_queue< int,vector<int>,decltype(p) > pq(p);
    

Check the constructors of the priority_queue class.

Constructors of priority_queue

user9335240
  • 1,739
  • 1
  • 7
  • 14