Привести указатель функции std::bind к void* и обратно

Допустим, я хочу связать функцию, а затем передать ее другой функции как void * и вернуть обратно.

У меня есть глобальная функция, в которой я пытаюсь выполнить функцию:

void function_wrapper(void * func){

std::function<void(const std::vector<double>&, const std::vector<double>&)> * function = reinterpret_cast<std::function<void(const std::vector<double>&, const std::vector<double>&)> *>(func);

std::function<void(const std::vector<double>&, const std::vector<double>&)> function_ = *function;
}

func, тем временем, создается как:

auto func = std::bind(&MyObj<dim>::myfunc, this, _1, _2);

Здесь dim — шаблонное целое число, равное 2, а function_wrapper вызывается через

function_wrapper((void *)(&func));

Между тем, myfunc является методом MyObj<dim> с типом:

void myfunc(const std::vector<double>& x, std::vector<double>& F) const;

Когда я пытаюсь вызвать function_wrapper, как описано выше, я получаю следующую ошибку при разыменовании:

Exception thrown: read access violation.

std::_Func_class<void,std::vector<double,std::allocator<double> > const & __ptr64,std::vector<double,std::allocator<double> > const & __ptr64>::_Getimpl(...) returned 0xFFFFFFFFFFFFFFFF.

If there is a handler for this exception, the program may be safely continued.

Я предполагаю, что у меня неправильная типизация моего приведения, но я не знаю, как правильно объявить тип. Каков правильный способ сделать это?


person user650261    schedule 04.12.2016    source источник


Ответы (1)


Результат std::bind не является std::function, как предполагает показанный код.

Таким образом, когда показанный код приводит указатель к возвращаемому значению из std::bind в void *, затем возвращает его обратно к указателю на std::function, затем вызывает объект функции или обращается к нему, это приводит к неопределенному поведению.

[func.bind.isbind] определяет std::bind следующим образом:

шаблон‹класс F, класс... BoundArgs› unspecified bind(F&& f, BoundArgs&&...bound_args);

С возвращаемым значением: "Оболочка переадресации вызовов g со слабым типом результата (20.9.2). Результат g(u1, u2, ..., uM) должен быть INVOKE (fd , std::forward(v1), std::forward(v2), ..., std::forward(vN), result_of_t)".

Вот и все. Класс, возвращаемый std::bind, не указан, и хотя для данной реализации C++, безусловно, разрешено каким-то образом создавать std::function, это не обязательно.

Но решение простое: явно присвойте возвращаемое значение из std::bind соответствующему std::function.

person Sam Varshavchik    schedule 05.12.2016
comment
Спасибо за ответ, но какое именно здесь решение? Каким должен быть мой возвращаемый тип? std::function является шаблонным типом, и использование выбранного мной шаблона не компилируется: ошибка C2893: не удалось специализировать шаблон функции «неизвестный тип std::invoke(_Callable &&,_Types &&...)» - person user650261; 05.12.2016
comment
Как я уже писал, решение состоит в том, чтобы явно присвоить возвращаемое значение из std::bind соответствующему std::function вместо auto. - person Sam Varshavchik; 05.12.2016
comment
Спасибо, но я предполагаю, что теперь я запутался в том, что не знаю, как ввести соответствующую функцию std::function, поскольку тот, который я написал, по-видимому, не правильный :) - person user650261; 05.12.2016
comment
Хорошо подумайте о том, каков будет ваш конечный результат выполнения привязки. Вы получаете вызываемый объект, который принимает определенные параметры и возвращает определенный тип. Это ваш std::function прямо здесь. - person Sam Varshavchik; 05.12.2016
comment
Хорошо, позвольте мне попытаться быть немного яснее. Я попытался просмотреть сигнатуру функции привязки. Я явно не правильно понял. Я провел много времени, играя с различными вариациями. Если вы видите, что я делаю неправильно при использовании std::function‹void(const std::vector‹double›&, const std::vector‹double›&)› в качестве типа возврата привязки, сообщите мне об этом. - person user650261; 05.12.2016