1

In SomeClass.h

class SomeClass{
    public:
        static std::vector<void (*)()> UpdateFuncs;
}

In OtherClass.h

class OtherClass{
    private:
        void Update();
    public:
        OtherClass();
}

In OtherClass.cpp

OtherClass::OtherClass(){
    Time::UpdateFuncs.push_back(&(this->Update));
}

On Build I get '&': illegal operation on bound member function expression and if I do:

.push_back(&Update);

Then I get "no instance of overloaded function

std::vector<_Ty, _Alloc>::push_back [with _Ty=void (*)(), _Alloc=std::allocator]" matches the argument list"

Thank in advance

4
  • 2
    &Update is not a void (*)(). This code can't work. What is your question? Commented Jan 21, 2018 at 13:10
  • My Question is how to change Update to make is work Commented Jan 21, 2018 at 13:15
  • You'd have to make Update static to get that type. Commented Jan 21, 2018 at 13:17
  • What are you trying to solve? Update is a non-static member, it has an implicit this argument. How do you expect to provide it at the call site? Commented Jan 21, 2018 at 13:18

2 Answers 2

1

OtherClass::Update is not suitable for a void (*)() function pointer, because it's a non-static member function; it's as if it had an "invisible" OtherClass* parameter.

Use std::function to achieve your goal:

#include <functional>

class Time
{
public:
    static std::vector<std::function<void()>> UpdateFuncs;
};

In OtherClass.cpp, use a this-capturing lamba as a function object:

OtherClass::OtherClass()
{
    Time::UpdateFuncs.push_back([this] { Update(); });
}

Of course, if you make Update static, then you can still work with void (*)() if you want to, because the "invisible" parameter is removed, but std::function is just the safe and modern way to do it.

Sign up to request clarification or add additional context in comments.

2 Comments

Excellent ! I didn't realize immediately that OP wanted not only the function pointer but also the target object. I have only one question: every created OtherClass will have a function referencing it in the vector; but how can you find back the entries that correspond to an object that is to be deleted in order to remove it from the vector ?
@Christophe: That question is too broad... it depends entirely on the rest of the program logic if, how, when and by whom objects are deleted.
0

The problem

You try to assign to an ordinary function pointer of type void(*)() a member function pointer of type void(OtherClass::*)().

Unfortunately these two types are incompatible: an ordinary function can be called with only its parameters, and a member function pointer can only be called for a specific object.

First solution : member function pointer

You have to change the definition of the vector to make it use a member function pointer.

class OtherClass;  // forward deaclaration
class SomeClass {
public:
    static std::vector<void (OtherClass::*)()> UpdateFuncs;
};

Then you can pushback the function as expected:

OtherClass::OtherClass() {
    SomeClass::UpdateFuncs.push_back(&OtherClass::Update);
}

Online demo

Unfortunately you can't mix it with member function pointers to other classes or ordinary function pointers. And you have to specify the object to use at the moment you invoke your function.

Better solution: command pattern

The command pattern allows you more flexibility than function pointers. Thanks to specialization of commands, you can mix commands that will invoke ordinary function pointers, member function pointers of different classes, or ad-hoc functions.

The commands could look like this:

class Command {
public: 
    virtual void execute() = 0; 
    virtual ~Command();
}; 

class CommandOtherClass : public Command { 
    OtherClass *target; 
    void (OtherClass::*f)(); 
public: 
    CommandOtherClass (void (OtherClass::*fct)(), OtherClass*t); 
    void execute() override; 
};

The implementation is really straightforward:

CommandOtherClass::CommandOtherClass (void (OtherClass::*fct)(), OtherClass*t) 
    :  f(fct),target(t) 
{
} 
void CommandOtherClass::execute() {
    (target->*f)();
}

The SomeClass function could be changed as follows:

class SomeClass {
public:
    static std::vector<unique_ptr<Command>> UpdateFuncs;
    static void executeAll();
};

Note that you could develop it so to include a registration and unregistration functions, so that you can also remove from the vector commands involving objects that no longer exist.

Adding a new command to the vector would be done like this:

OtherClass::OtherClass() {
    SomeClass::UpdateFuncs.push_back(make_unique<CommandOtherClass>(&OtherClass::Update, this));
}

Finally, here a complete online demo that invokes two commands automatically registered for some local objects, and even add a third ad hoc command unrelated to any other object.

2 Comments

While this is 100% true, the error shown in the question arise actually because &(this->Update) should be *OtherClass::Update.
@Holt Yes, I've edited and added some code to make it clearer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.