Выполнение связанного std :: function throws std :: bad_function_call

Я хочу привязать функцию-член к std::function<void(void)>, Я слышал, что функции-члены принимают один дополнительный параметр, который является указателем экземпляра. Поэтому я звоню std::bind(&Class::Function, this, parameter) но когда я выполняю объект функции, он выдает ошибку во время выполнения.

Необработанное исключение в 0x748D4B32 в Application.exe: Microsoft C ++
исключение: std :: bad_function_call в ячейке памяти 0x0114F4E8.

Параметр является указателем на один из моих structs. Как я делаю не так? Какая дополнительная информация вам нужна?

Обновление: вот мой код.

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

Решение

В комментариях выше было отмечено несколько разных проблем. Чтобы устранить их, попробуйте внести следующие изменения в код:

struct Pass{ std::function<void(Pass *)> Function; /* ... */ };

// ...

case FORMS:
pointer->Function =
std::bind(&ModuleRenderer::DrawForms, this, std::placeholders::_1);
break;

Не связывайте Pass * на вызов функции только что, потому что, как @molbdnilo указывает, что указатель станет недействительным при вызове AddPass() несколько раз, и вектор изменяется.

Так как std::function сейчас занимает Pass *Вам нужно указать правильный указатель при его вызове.

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
}
1

Другие решения

passes.push_back(std::make_pair(Name, pass));
Pass *pointer = &(passes.back().second);

Тот pointer станет недействительным, когда вы позже push_back и вектор растет.

Вы можете вообще избегать указателей и передавать указатель соответствующего объекта вместо указателя.

pointer->Function = std::bind(&ModuleRenderer::DrawForms, this, passes.size() - 1);

// ...

void DrawForms(size_t i)
{
Pass& pass = passes[i].second;
// Handle as before...
}
1

По вопросам рекламы [email protected]