Demote boost:: function to plain function pointer
хочу передать boost:: bind к методу, ожидающему простого указателя функции (та же подпись).
typedef void TriggerProc_type(Variable*,void*);
void InitVariable(TriggerProc_type *proc);
boost::function<void (Variable*, void*)> triggerProc ...
InitVariable(triggerProc);
error C2664: 'InitVariable' : cannot convert parameter 1 from
'boost::function<Signature>' to 'void (__cdecl *)(type *,void *)'
Я могу избежать сохранения функции boost:: и просто передать связанный функтор напрямую, но затем я получаю аналогичную ошибку:
error C2664: 'blah(void (__cdecl *)(type *,void *))' : cannot convert parameter
1 from 'boost::_bi::bind_t<R,F,L>' to 'void (__cdecl *)(type *,void *)'
Ответы
Ответ 1
Кто-нибудь заметил, что принятый ответ работает только с тривиальными случаями? Единственный способ, которым функция < > :: target() возвращает объект, который может быть привязан к обратному вызову C, - это если он был сконструирован с объектом, который может быть связан с обратным вызовом C. Если это так, то вы могли бы связать его напрямую и пропустить всю функцию < > ерунда для начала.
Если вы думаете об этом, нет волшебного решения. Обратный вызов C-стиля хранится как один указатель, который указывает на исполняемый код. Для любой нетривиальной boost:: function < > потребуется по крайней мере два указателя: один для исполняемого кода, другой - данные, необходимые для настройки вызова (например, указатель 'this', в случае связанного члена функция).
Правильный способ использования boost:: function и boost:: bind с обратными вызовами C заключается в создании функции прокладки, которая удовлетворяет сигнатуре обратного вызова, определяет, какую функцию < > для вызова и вызывает ее. Обычно обратные вызовы C будут иметь какой-то вид void * для "пользовательских данных"; что, когда вы нажимаете указатель на функцию:
typedef void (*CallbackType)(int x, void* user_data);
void RegisterCallback(CallbackType cb, void* user_data);
void MyCallback(int x, void* userData) {
boost::function<void(int)> pfn = static_cast<boost::function<void(int)> >(userData);
pfn(x);
}
boost::function<void(int)> fn = boost::bind(myFunction(5));
RegisterCallback(MyCallback, &fn);
Конечно, если ваша сигнатура обратного вызова не включает какой-то указатель пользовательских данных, вам не повезло. Но любой обратный вызов, который не включает указатель пользовательских данных, уже непригоден для большинства реальных сценариев и нуждается в перезаписи.
Ответ 2
Я думаю, что вы хотите использовать функцию-член target() функции boost:: (не так ли...)
#include <boost/function.hpp>
#include <iostream>
int f(int x)
{
return x + x;
}
typedef int (*pointer_to_func)(int);
int
main()
{
boost::function<int(int x)> g(f);
if(*g.target<pointer_to_func>() == f) {
std::cout << "g contains f" << std::endl;
} else {
std::cout << "g does not contain f" << std::endl;
}
return 0;
}
Ответ 3
Вы можете заставить его работать со связью?
cb_t cb = *g.target<cb_t>(); //target returns null
Это по дизайну. В принципе, поскольку bind
возвращает совершенно другой тип, нет способа, которым это будет работать. В принципе, объект-связующий объект не может быть преобразован в указатель функции C (поскольку он не один: это объект функции). Тип, возвращаемый boost::bind
, является сложным. Текущий стандарт С++ не позволяет вам делать то, что вы хотите. С++ 0x будет иметь выражение decltype
, которое можно использовать здесь для достижения чего-то подобного:
typedef decltype(bind(f, 3)) bind_t;
bind_t target = *g.target<bind_t>();
Обратите внимание, что это может работать или не работать. У меня нет возможности проверить его.
Ответ 4
см. страницу расширенной рассылки
[boost] [Function] Проблема с использованием target() с boost:: mem_fn и boost:: bind
Ответ 5
Вы можете заставить его работать со связью?
#include <boost/function.hpp>
#include <boost/bind.hpp>
void f(int x)
{
(void) x;
_asm int 3;
}
typedef void (*cb_t)(int);
int main()
{
boost::function<void (int x)> g = boost::bind(f, 3);
cb_t cb = *g.target<cb_t>(); //target returns null
cb(1);
return 0;
}
update: Хорошо, что цель - связать метод с функцией-обратным вызовом. так что теперь?