简体   繁体   中英

std::function does not work, but plain old function pointer does - why?

I want to make a function that will take std::function as a parameter, and inside call that passed function:

void handleCollision(std::function<void(const Entity&)>& resolveCollision, const Entity& block) {
    if (playerInRangeOf(block) && playerIntersects(block)) {
        resolveCollision(block);
    }
}

And the caller (within the same Class):

for (auto&& block : blocks) {
    handleCollision(resolveCollisionAxisX, block);
}

Error:

Reference to non-static member function must be called
error: no matching function for call to 'StateGame::handleCollision(<unresolved overloaded function type>, Block&)'
handleCollision(resolveCollisionAxisX, block);
                                            ^

However , if I follow with C-style function pointers:

void handleCollision(void (StateGame::*resolveCollision)(const Entity&), const Entity& block) {
    if (playerInRangeOf(block) && playerIntersects(block)) {
        (this->*resolveCollision)(block);
    }
}

Then it does work fine (caller is the same).

How can I make the std::function work? Side note: I don't want to make anything static.

Wrap it in a lambda, replace

handleCollision(resolveCollisionAxisX, block)

to

[this](const Entity& e){
   this->resolveCollisionAxisX(e);
}

Also replace std::function<void(const Entity&)>& to std::function<void(const Entity&)> or const std::function<void(const Entity&)>&

C++ member functions are plain C function with the addition of the instance address as the first parameter.

For instance, void StateGame::resolveCollisionAxisX(const Entity&) for the compiler is equivalent to void resolveCollisionAxisX(StateGame* instance, const Entity&)

Here a small code snippet showing a working example. See how the std::function template parameter is void(A*) and not just void() .

#include <iostream>

#include <functional>

struct A{
  void foo1(void(A::*resolveCollision)(void)){
    std::cout << "foo [c-style]" << std::endl;
    (this->*resolveCollision)();
  }

  void foo2(std::function<void(A*)> resolveCollision) {
    std::cout << "foo [std::function]" << std::endl;
    resolveCollision(this);
  }

  void target() {
    std::cout << "resolve" << std::endl;
  }

  void caller() {
    std::cout << "caller" << std::endl;
    foo1(&A::target);
    foo2(&A::target);
  }
};

int main() {
  A a;
  a.caller();
}

If you know Python, there it is more explicit this concept, in fact, all member functions have self as first parameter (which is the alter ego of this in C++).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM