Search code examples
c++function-pointerspointer-to-member

C++ assigning member function pointer to non-member function pointer


Hy everyone, I am quite new with OOP in C++ [go easy on me :) ] and I am trying to build a class in which a class member function needs to be taken from outside the class. I thought of doing it by declaring a function pointer member and creating a member function that takes as input a pointer to the function that I want to include in the class and sets the member pointer to the input.

This is how I am trying to do it:

class A{
    std::vector<double> *(A::*obj) (std::vector<double> x);
    void set_obj(std::function<std::vector<double>>* Po);
};

void A::set_obj(std::function<std::vector<double>>* Po){
    this->obj = Po;
}

I am getting the following error:

error: Assigning to 'std::vector<double> *(A::*)(std::vector<double>)' from incompatible type 'std::function<std::vector<double>> *'

I can also add that I am open to alternative solutions which do not imply the use of function pointers.


Solution

  • There are a couple of issues. First, 'pointer-to-member' types are an advanced (and, dare I say, esoteric) feature for accessing member functions as pointers. Since you've got an std::function (which, when it comes down to it, is some sort of ordinary function, not a member function), you don't need pointer-to-member.

    Second, you can't use ordinary function pointers since std::function is, again, more general. The former will only accept actual top-level functions (and closures which do not close around anything, which are trivially converted to top-level functions). The latter accepts top-level functions, closures, and functors. Now, in modern C++, you want std::function, since it's more general and abstract and just generally less confusing. So I suggest making the member variable have std::function type.

    using MyFunction = std::function<std::vector<double>(std::vector<double>)>;
    
    class A{
        MyFunction obj;
        void set_obj(MyFunction obj);
    };
    
    void A::set_obj(MyFunction obj){
        this->obj = std::move(obj);
    }
    

    I've also gotten rid of the raw pointer. You don't need it, and generally as you're learning C++ you should stay away from it. I've taken the argument by value, so that we can std::move it into the instance variable. We still copy the function into once when we call this member function, but std::function is always copy-assignable

    std::function satisfies the requirements of CopyConstructible and CopyAssignable.