Thore
Thore

Reputation: 1838

Passing a member function as parameter of a member function

I'm busy with making a leveleditor class in an engine but I'm stuck at passing a member function as parameter of another member function.

First I've made a typedef

typedef void (LevelEditor::*CallFunctionPtr)();

Then I have made a member function to check if the user clicks with his mouse on a hitregion. If so, another function needs to be called. So I've my first member function with 2 parameters

LevelEditor.h

void CheckClickCollision(HitRegion* region, CallFunctionPtr callFunctionPtr);

LevelEditor.cpp

void LevelEditor::CheckClickCollision( HitRegion* region, CallFunctionPtr callFunctionPtr)
{
    if(GAME_ENGINE->GetLButtonMouseState())
    {
        if(!m_bIsLeftPressed && region->HitTest(m_MousePosition))
            (this->*callFunction)();

        m_bIsLeftPressed = true;
    }
    else
        m_bIsLeftPressed = false;   
}

Then I've two stupid example member functions:

LevelEditor.h

void LevelUp();
void LevelDown();

LevelEditor.cpp

void LevelEditor::LevelUp()
{
    ++m_iCurrentLevel;
}

void LevelEditor::LevelDown()
{
    if(m_iCurrentLevel > 0)
        --m_iCurrentLevel;
    else
        return;
}

And now I want to call that function every tick to check if there is a hit. So in my tick function:

CheckClickCollision(m_LeftArrowRegionPtr, LevelDown);
CheckClickCollision(m_RightArrowRegionPtr, LevelUp);

And here I get the error on LevelDown and Levelup:

Error: argument of type void (LevelEditor::*)()" is incompatible with parameter of type "CallFunctionPtr *"

Dont know how to fix it. Tried different things, nothing worked

Upvotes: 1

Views: 298

Answers (2)

Viktor Latypov
Viktor Latypov

Reputation: 14467

Try

CheckClickCollision(m_LeftArrowRegionPtr, &LevelEditor::LevelDown);
CheckClickCollision(m_RightArrowRegionPtr, &LevelEditor::LevelUp);

For your convenience, here's the working sample (the compiler is GCC 4.7):

#include <stdio.h>

class LevelEditor;

typedef void (LevelEditor::*CallFunctionPtr)();

class LevelEditor
{
public:
    LevelEditor() {}

    void CheckClickCollision(void* region, CallFunctionPtr callFunction)
    {
        (this->*callFunction)();
    }

    void LevelUp() { printf("up\n"); }
    void LevelDown() { printf("down\n"); }

    void Test()
    {
        CheckClickCollision(NULL, &LevelEditor::LevelDown);
        CheckClickCollision(NULL, &LevelEditor::LevelUp);
    }
};

int main()
{
    LevelEditor e;
    e.Test();

    return 0;
}

The other way to call this:

    void Test()
    {
        CallFunctionPtr p;
        p = &LevelEditor::LevelDown;
        CheckClickCollision(NULL, p);
        p = &LevelEditor::LevelUp;
        CheckClickCollision(NULL, p);
    }

Upvotes: 1

Puppy
Puppy

Reputation: 146910

You need to use std::function and std::bind, or lambdas if you have a supporting compiler.

void LevelEditor::CheckClickCollision( HitRegion* region, std::function<void()> callFunction)
{
    if(GAME_ENGINE->GetLButtonMouseState())
    {
        if(!m_bIsLeftPressed && region->HitTest(m_MousePosition))
            callFunction();

        m_bIsLeftPressed = true;
    }
    else
        m_bIsLeftPressed = false;   
}

void Test()
{
    // lambda
    CheckClickCollision(NULL, [this] { LevelDown(); });
    // bind
    CheckClickCollision(NULL, std::bind(&LevelEditor::LevelDown, this));
}

Upvotes: 0

Related Questions