0

I'm developing this program to run Dijkstra's Algorithm with an heap implementation and I want it to be as versatile as it can be so I'm using function pointer in order to avoid code repetition. This is the error that it pops. I'm using the stl make_heap

"Type must use '.*' or '->*' to call pointer-to-member function in '__comp (...)', e.g. '(... ->* __comp) (...)' "heap.h     C/C++ Problem

Here is Dijkstra's Algorithm:

void Graph::dijkstraAlg(Vertex* ini, Vertex* fin, void(Graph::*weight_filler)(void), bool(Graph::*pq_order)(const Vertex* &, const Vertex* &)){

for(unsigned int i = 0; i < vertexs.size(); i++) {
    vertexs[i]->path = NULL;
    vertexs[i]->holder = MAX_INT_VALUE;
    vertexs[i]->processing=false;
}

(this->*weight_filler)();

Vertex* v=ini;
v->holder = 0;
v->processing = true;

vector<Vertex*> pq;
pq.push_back(v);
make_heap(pq.begin(),pq.end(),pq_order);

while(!pq.empty()){

    v=pq.front();
    pop_heap(pq.begin(),pq.end());
    pq.pop_back();

    for(unsigned int u=0; u < v->adj.size(); u++){

        Vertex* w = v->adj[u]->dest;

        if((v->holder+v->adj[u]->weight) < w->holder){

            w->holder=v->holder + v->adj[u]->weight;
            w->path=v;

            if(!w->processing){

                w->processing=true;
                pq.push_back(w);
            }
        }

        make_heap(pq.begin(),pq.end(),pq_order);
    }
}

return;}

The error is in the make_heap and I can't figure it out, any help is appreciated.

Here is the function I'm passing to the make_heap:

bool Graph::regular_PqOrder(const Vertex* &v, const Vertex* &u){
return v->holder > u->holder;}

This is how I call the algo:

dijkstraAlg(i,f,&Graph::price_WeightFiller,&Graph::regular_PqOrder);

If you need more information just tell me and I edit it. Thank you pal's

  • how is this being called? you should be appending & before function being passed to your algo – Sarang Apr 22 '15 at 18:29

2 Answers2

2

You're passing the wrong type. std::make_heap takes a functor as the third element, which should satisfy the requirements of Compare, which are that you need:

bool operator()(const Type1&, const Type2&) const;

You are passing in pq_order which is of type:

bool(Graph::*)(const Vertex* &, const Vertex* &)

That's a pointer-to-member, it's not callable without an object of type Graph. Hence the error about "Type must use '.' or '->' to call pointer-to-member". The simplest approach is to simply provide that object, which in your case is this:

using namespace std::placeholders;
std::make_heap(pq.begin(), pq.end(), 
    std::bind(pq_order, this, _1, _2));

Alternatively, since regular_PqOrder doesn't actually rely on any of the members of other methods of Graph, you could also just be to make it static:

class Graph { 
public:
    static bool regular_PqOrder(const Vertex* &v, const Vertex* &u) 
    {
        return v->holder > u->holder;
    }
};

And pass in Graph::regular_PqOrder now as a function pointer, rather than pointer-to-method.

Barry
  • 286,269
  • 29
  • 621
  • 977
1

I have simplified your problem to:

#include <algorithm>
#include <vector>

using namespace std;

class Vertex
{};

class Graph
{
public:
    void dijkstraAlg(Vertex* ini, Vertex* fin, void(Graph::*weight_filler)(void), 
                                               bool(Graph::*pq_order)(const Vertex*, const Vertex*))
    {
        (this->*weight_filler)();

        struct Comparator
        {
        private:

            Graph* m_g;
            bool(Graph::*m_fn)(const Vertex*, const Vertex*);
        public:
            Comparator(Graph* g, bool(Graph::*fn)(const Vertex*, const Vertex*)) : m_g(g), m_fn(fn)
            {}

            bool operator()(const Vertex* one, const Vertex* two) const
            {
                return (m_g->*m_fn)(one, two);
            }
        };

        Comparator comparator(this, pq_order);

        vector<Vertex*> pq;
        std::make_heap(pq.begin(), pq.end(), comparator);
    }

    void weight_filler1()
    {        
    }
    bool pq_order1(const Vertex*, const Vertex*)
    {
        return false;
    }

};

int main()
{
    Graph g;
    g.dijkstraAlg(nullptr, nullptr, &Graph::weight_filler1, &Graph::pq_order1);

    return 0;
}

The problem is: std::make_heap expects a function pointer- in your case you are passing a pointer to member function thus the issue.

Either you can change the declaration of dijkstraAlg to take in just a static function pointer pq_order or wrap up pq_order in a structure to make it a callable entity in itself like I have done.

Note: you will have to fixup references to pointers in pq_order for make_heap to compile anyway

Sarang
  • 1,867
  • 1
  • 16
  • 31