Assign different functions to different structs in std::vector<>

Started by
21 comments, last by coope 8 years, 6 months ago

With a little help by stackoverflow: http://stackoverflow.com/questions/1485983/calling-c-class-methods-via-a-function-pointer


class Foo {
public:
    void f() { std::cout << "hello world" << std::endl; }
};

int main()
{
    Foo x;
    void (Foo::*g)();

    g = &Foo::f;
    (x.*g)();
    return 0;
}
Advertisement

The problem is that a member function has an implicit "this" pointer as the first argument, to know what object to work with.

That's why assigning it to a void function pointer won't work.

Also, you need to keep the pointer to the object around, so you can pass it along when calling the callback later.

The C++11 way to solve it:

class Menu {

std::function<void()> onMenuClick;

};

class Foo {

void f();

};

Menu menu;

Foo x;

menu.onMenuClick = [&x] () { x.f() }; //using wrapper lambda

OR

menu.onMenuClick = std::bind(&Foo:f, &x); //using bind

the thing is i store a pointer to function in one struct

then in another struct i try to assign the function (from this structure)


struct TDropDownMenu
{
pt2Function MenuOnClick;
TDropDownMenu * Items;
};


struct TTERRA_TEX_OSD
{
void SetNoBlend()
{
some code here
}


TDropDownMenu menu;
void Init()
{
menu.Items[0].Items[0].MenuOnClick = &SetNoBlend();
}

Thats what i am trying to do.

EDIT.

i did what

Olof Hedman told to do.

after enabling c++11 support on android compiler it compiles, theres also lotta work to see if this works

but for now i thank you for support

now my code looks like this:


#include <functional>
struct TDropDownMenu
{

	 std::function<void()> MenuOnClick;
};



other header

struct TTERRA_TEX_OSD
{
void SetNoBlend() { brush_blend = 0; }
void Init()
{
BrushMenu.Items[3].Items[0].MenuOnClick = std::bind(&TTERRA_TEX_OSD::SetNoBlend, this);
}
};

I encountered a problem with:

std::function<void(int)> SpecialMenuOnClick;

LayerMenu.Items[3+i].Items[0].SpecialMenuOnClick = std::bind(&TTERRA_TEX_OSD::SelectLayer, this);

void SelectLayer(int index)

{
selected_layer = index;
}
this doesn't work :/
using std::bind gives me an error:
no match for 'operator=' (operand types are 'std::function<void(int)>' and 'std::_Bind_helper<false, void (TTERRA_TEX_OSD::*)(int), TTERRA_TEX_OSD* const>::type {aka std::_Bind<std::_Mem_fn<void (TTERRA_TEX_OSD::*)(int)>(TTERRA_TEX_OSD*)>}')
LayerMenu.Items[3+i].Items[0].SpecialMenuOnClick = std::bind(&TTERRA_TEX_OSD::SelectLayer, this, std::placeholders::_1);
Should probably do the trick although I have not used any bind since C++11 was around. See this for more details.


using std::bind gives me an error:
I would suggest against using std::bind, it has some caveats and it keeps getting worse and worse the more advanced usage you need for it. It is also particularly opaque to the compiler. It seems I'm not the only one. I mean seriously.

Just use a standard lambda. Is this what you're trying to do?


LayerMenu.Items[3+i].Items[0].SpecialMenuOnClick = [this]() { this->SelectLayer(); };

Previously "Krohm"

Thanks for those video links Krohm.

I thought about adding something about preferring lambdas, but I didn't have time to write it clearly... (but at least I wrote the lambda as the first option in my post)

Didn't know bind was _that_ bad though, now I have more arguments for always using wrapper lambdas.


LayerMenu.Items[3+i].Items[0].SpecialMenuOnClick = std::bind(&TTERRA_TEX_OSD::SelectLayer, this, std::placeholders::_1);

compiles

but


LayerMenu.Items[3+i].Items[0].SpecialMenuOnClick = [this]() { this->SelectLayer(); };

doesn't

no match for 'operator=' (operand types are 'std::function<void(int)>' and 'TTERRA_TEX_OSD::ReInit_LayerMenu()::__lambda0')

can someone tell me why?

The same reason as why you needed the _1 for the bind. You create a lambda taking no parameter and assign it to something expecting an int-argument.

LayerMenu.Items[3+i].Items[0].SpecialMenuOnClick = [this](int index) { this->SelectLayer(index); };

thanks

This topic is closed to new replies.

Advertisement