问题
I want to bind a member function to a std::function<void(void)>
. I heard that member functions take one extra parameter which is the instance pointer. Therefore I call std::bind(&Class::Function, this, parameter)
but when I execute the function object, it throws a runtime error.
Unhandled exception at at 0x748D4B32 in Application.exe: Microsoft C++ exception: std::bad_function_call at memory location 0x0114F4E8.
The parameter is a pointer to one of my own struct
s. How am I doing wrong? What additional information do you need?
Update: Here is my code.
class ModuleRenderer
{
struct Pass{ std::function<void()> Function; /* many more members... */ };
std::vector<std::pair<std::string, Pass>> passes;
enum Drawfunc{ FORMS, SKY, LIGHTS, QUAD, SCREEN };
void AddPass(std::string Name, Drawfunc Function)
{
Pass pass;
// set some of the members
// ...
passes.push_back(std::make_pair(Name, pass));
Pass *pointer = &(passes.back().second);
switch (Function)
{
case FORMS:
pointer->Function = std::bind(&ModuleRenderer::DrawForms, this, pointer);
break;
// analogeously for the other cases
// ...
}
}
void DrawForms(Pass *pass)
{
// ...
}
// is called consecutively after adding all passes
void Update()
{
for(auto i : passes)
// some initializing based on members of pass
i.Function();
}
};
回答1:
A couple of different issues have been pointed out in the comments above. To resolve these, try making the following changes to your code:
struct Pass{ std::function<void(Pass *)> Function; /* ... */ };
// ...
case FORMS:
pointer->Function =
std::bind(&ModuleRenderer::DrawForms, this, std::placeholders::_1);
break;
Do not bind the Pass *
to the function call just yet, because, as @molbdnilo points out, that pointer will become invalid when you call AddPass()
multiple times and the vector is resized.
Since the std::function
now takes a Pass *
, you need to supply the correct pointer when you invoke it.
void Update()
{
for(auto& i : passes) { // <-- take a reference, don't copy
// some initializing based on members of pass
i.Function( &i ); // pass Pass * to the function
}
回答2:
passes.push_back(std::make_pair(Name, pass));
Pass *pointer = &(passes.back().second);
That pointer
will become invalid when you later push_back
and the vector grows.
You could avoid pointers altogether and pass the index of the corresponding object instead of a pointer.
pointer->Function = std::bind(&ModuleRenderer::DrawForms, this, passes.size() - 1);
// ...
void DrawForms(size_t i)
{
Pass& pass = passes[i].second;
// Handle as before...
}
来源:https://stackoverflow.com/questions/17200804/executing-bound-stdfunction-throws-stdbad-function-call