jeudi 3 septembre 2020

Is it possible to access the arguments from an std::bind object?

Please consider the following scenario.

A hypothetical pop-up menu class that displays some actions, and when one of them is selected it will call the passed in action which is in form of an std::function:

PopupMenu::PopupMenu(std::function<void(RowItem*)> editRowFunction, RowItem *item)
    : _editRowFunction(editRowFunction)
    , _item(item) {
}

Then at some point it might call execute:

PopupMenu::execute(} {
    _editRowFunction(_item);
}

Then I have this other class that's a UI object:

class EditorWidget {
    void editRow(RowItem *row) {
        //edit the row
    }
}

And here's how I am using all of them:

int main() {
    auto item = new RowItem();
    auto editorWidget = new EditorWidget();
    PopupMenu menu(std::bind(&EditorWidget::editRow, editorWidget, item), item);
    menu.execute();
    return 0;
}

Everything works. My question is the following: If I am already passing the argument item in std::bind, why do I have to pass it again as a second parameter in order to be able to call the bound function with that argument? If I don't, and try to call the function just by itself from PopupMenu::execute(), I get a compiler error.

The other way around it is to make the constructor of PopupMenu like this:

PopupMenu::PopupMenu(std::function<void()> editRowFunction)
    : _editRowFunction(editRowFunction) {}

And if I do it that way then I call it this way:

PopupMenu::execute() {
_editRowFunction();
}

What I don't like about this method is that I can pretty much pass any bound function in the PopupMenu constructor and it will be called. But that's not what I want, I want to enforce only a function with a specific signature.

I can also pass a lambda, yes. But let's try to solve it without lambdas. Thank you all in advance for your help.

Aucun commentaire:

Enregistrer un commentaire