3

I have a vector containing function pointers

typedef bool (*fPtr)();
vector<fPtr> AlgoDB;

The functions that I push into the vectors are defined as below

bool SAlgos1::Algo1() {
    cout << "Executing Algo1" << endl;
    return true;
} 

The below statement is used to add the functions / pointers to the vector

this->AlgoDB.push_back((fPtr) &this->Algo1);

This being the traditional C styled function pointer usage, I am trying to use the std::function, where the vector and the functions are modified now as below

typedef function<bool()> ffptr;
vector <ffptr> fAlgoDB;

function<bool()> SAlgos1::fAlgo1(){

    cout << "Executing FAlgo1";
    return true;
}

But now whenever I use the statement like this

this->fAlgoDB.push_back(fAlgo1); or this->fAlgoDB.push_back(&fAlgo1); (typecasting doesn't help too - this->fAlgoDB.push_back((ffptr) this->fAlgo1);)

I get an error stating

error: taking address of temporary [-fpermissive] and

error: could not convert 'true' from 'bool' to 'std::function<bool()>' (even though I dont really call the function) for every alternate compilation.

How can I store the functions or function pointers in the vector? What is the compiler trying to convey?

Bharadwaj
  • 737
  • 6
  • 26
  • 2
    You are *returning* an `std::function` from `fAlgo1` where you should return a `bool`. Also, your original code shouldn't even work with member functions because you have to state the type of the class in your function pointer typedef! – Felix Dombek Aug 16 '16 at 11:24
  • The original function works without the class type, its a compiler warning though! – Bharadwaj Aug 16 '16 at 11:25
  • You are invoking undefined behaviour if you define a function pointer to point to a global function, but instead use it to store a member function and then invoke it. Your `(fPtr)` cast simply hides the fact that you're casting incompatible things. Better to not use C style casts! – Felix Dombek Aug 16 '16 at 11:28

2 Answers2

6

There are two problems in your example.

  1. You changed the return type of your function from bool to function<bool>. Just leave it as bool, since that is the return type you want.
  2. The the type of pointer-to-member-function is different from pointer-to-function (see https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types). This is due to the fact that a member function always passes the this pointer as an argument. You need to bind that argument (using std::bind, see https://stackoverflow.com/a/7582576/6095394).

The following example compiles fine.

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

using namespace std;

class SAlgos1
{
    typedef function<bool()> ffptr;

    bool fAlgo1()
    {
        cout << "Executing FAlgo1";
        return true;
    }

    void fillAlgoDB()
    {
        fAlgoDB.push_back(bind(&SAlgos1::fAlgo1, this));
    }

    vector<ffptr> fAlgoDB;
};
Community
  • 1
  • 1
pschill
  • 5,055
  • 1
  • 21
  • 42
  • 2
    I would use lambda instead of `bind`. `bind` was a necessity when we didn't have lambdas. Now it's just a monster sitting in a corner. Since c++14 it became completely obsolete. – bolov Aug 16 '16 at 11:48
  • 2
    @bolov: Only since C++14, though. The question is tagged [tag:c++11] and, in C++11, the lack of generic lambdas makes `std::bind` preferable in several scenarios. Mind you, this isn't one of them. I guess that's all the same as what you said. – Lightness Races in Orbit Aug 16 '16 at 11:50
  • @LightnessRacesinOrbit exactly – bolov Aug 16 '16 at 11:51
1

You are returning an std::function from fAlgo1 where you should return a bool. Also, your original code shouldn't even work with member functions because you have to state the type of the class in your function pointer typedef!

The syntax is explained here. You could use

typedef bool (SAlgos1::*fPtr)();

to fix the function pointer.

Right now, you are invoking undefined behaviour because you declare a function pointer to point to a global function, but instead use it to store a member function and then invoke it. Your (fPtr) cast simply hides the fact that you're casting incompatible things. Better to not use C style casts!

Felix Dombek
  • 13,664
  • 17
  • 79
  • 131
  • This I understood, there is a mistake with the return parameter, as I do not know the syntax to define a member function which is actually std::function. thank you for that, but how do I define and push the std::function (member function) in the vector? – Bharadwaj Aug 16 '16 at 11:41
  • 1
    Use `this->AlgoDB.push_back(std::bind(&SAlgos1::fAlgo1, this));` – Felix Dombek Aug 16 '16 at 11:44