将std :: bind转换为函数指针 [英] convert std::bind to function pointer

查看:1105
本文介绍了将std :: bind转换为函数指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个第三方库,它有一个函数指针作为第一个参数的方法:

  int third_party_method (void(* func)(double *,double *,int,int,double *),...); 

我想传递一个指向类的方法的指针,声明如下:

  class TestClass 
{
public:
void myFunction(double *,double *,int,int, void *);

我试图通过这个函数,如下:

  TestClass * tc = new TestClass(); 
using namespace std :: placeholders;
third_party_method(std :: bind(& TestClass :: myFunction,tc,_1,_2,_3,_4,_5),...);

但是,这不会编译:

 将参数1从'std :: tr1 :: _ Bind< _Result_type,_Ret,_BindN>'转换为'void(__cdecl *)(double *,double *,int,int,void *)'不可能
with
[
_Result_type = void,
_Ret = void,
_BindN = std :: tr1 :: _ Bind6< std :: tr1 :: _ Callable_pmf ]

有没有办法我可以将成员传递给函数?

解决方案


有没有办法可以将成员传递给函数?


除非你的类对象是某种全局对象 - 这是不可能的。因为对象可能包含一些数据,而函数指针只是指向函数的指针 - 它不包含任何运行时上下文,只有编译时的上下文。



每个回调传递的编译时唯一ID,那么您可以使用以下广义方法。



用法:

  void test(void(* fptr)())
{
fptr();
}

struct SomeStruct
{
int data;
void some_method()
{
cout<<数据< endl;
}
void another_method()
{
cout<< -data<< endl;
}
}; SomeStruct local [] = {{11},{22},{33}};

int main()
{

test(get_wrapper< 0>(boost :: bind(& SomeStruct :: some_method,local [0])));
test(get_wrapper< 1>(boost :: bind(& SomeStruct :: another_method,local [0])));

test(get_wrapper< 2>(boost :: bind(& SomeStruct :: some_method,local [1])));
test(get_wrapper< 3>(boost :: bind(& SomeStruct :: another_method,local [1])));

test(get_wrapper< 4>(boost :: bind(& SomeStruct :: some_method,local [2]
test(get_wrapper< 5>(boost :: bind(& SomeStruct :: another_method,local [2])));
}

它可能不需要每次调用的唯一ID,例如,有不同的类型,或者其使用的运行时范围不重叠。



实施:



实验演示

  #include< boost / optional.hpp> 
#include< boost / bind.hpp>
#include< iostream>
#include< ostream>
using namespace std;

template< unsigned ID,typename Functor>
boost :: optional< Functor> & get_local()
{
static boost :: optional< Functor>本地;
return local;
}

template< unsigned ID,typename Functor>
typename Functor :: result_type wrapper()
{
return get_local< ID,Functor>()。get()
}

template< typename ReturnType>
struct Func
{
typedef ReturnType(* type)();
};

template< unsigned ID,typename Functor>
typename Func< typename Functor :: result_type> :: type get_wrapper(Functor f)
{
(get_local< ID,Functor>())= f;
return wrapper< ID,Functor> ;;
}

// ----------------------------------- -----------------------------------

void test(void(* fptr )())
{
fptr();
}

struct SomeStruct
{
int data;
void some_method()
{
cout<<数据< endl;
}
void another_method()
{
cout<< -data<< endl;
}
}; SomeStruct local [] = {{11},{22},{33}};

int main()
{

test(get_wrapper< 0>(boost :: bind(& SomeStruct :: some_method,local [0])));
test(get_wrapper< 1>(boost :: bind(& SomeStruct :: another_method,local [0])));

test(get_wrapper< 2>(boost :: bind(& SomeStruct :: some_method,local [1])));
test(get_wrapper< 3>(boost :: bind(& SomeStruct :: another_method,local [1])));

test(get_wrapper< 4>(boost :: bind(& SomeStruct :: some_method,local [2]
test(get_wrapper< 5>(boost :: bind(& SomeStruct :: another_method,local [2])));
}






注意多线程访问 - 在这种情况下,您应该使用某种类型的线程本地存储数据。 p>

I have a third-party library which has a method that takes a function pointer as the first parameter:

int third_party_method(void (*func)(double*, double*, int, int, double*), ...);

I want to pass a pointer to a class' method that is declared as follows:

class TestClass
{
    public:
        void myFunction (double*, double*, int, int, void*);

I tried to pass this function as follows:

TestClass* tc = new TestClass();
using namespace std::placeholders;
third_party_method(std::bind(&TestClass::myFunction, tc, _1, _2, _3, _4, _5), ...);

However, this does not compile:

Conversion of parameter 1 from 'std::tr1::_Bind<_Result_type,_Ret,_BindN>' to 'void (__cdecl *)(double *,double *,int,int,void *)' is not possible
with
[
    _Result_type=void,
    _Ret=void,
    _BindN=std::tr1::_Bind6<std::tr1::_Callable_pmf<void (__thiscall TestClass::* const )(double *,double *,int,int,void *),TestClass,false>,TestClass *,std::tr1::_Ph<1>,std::tr1::_Ph<2>,std::tr1::_Ph<3>,std::tr1::_Ph<4>,std::tr1::_Ph<5>>
]

Is there any way I can pass the member to the function?

解决方案

Is there any way I can pass the member to the function?

Unless your class object is some kind of global object - it is not possible. Because objects may contain some data, while function pointer is just pointer to function - it doesn't contain any runtime context, only compile-time one.

If you accept having compile-time unique IDs for each callback passing, then you can use following generalized approach.

Usage:

void test(void (*fptr)())
{
    fptr();
}

struct SomeStruct
{
    int data;
    void some_method()
    {
        cout << data << endl;
    }
    void another_method()
    {
        cout << -data << endl;
    }
};

int main()
{
    SomeStruct local[] = { {11}, {22}, {33} };

    test(get_wrapper<0>(  boost::bind(&SomeStruct::some_method,local[0]) ));
    test(get_wrapper<1>(  boost::bind(&SomeStruct::another_method,local[0]) ));

    test(get_wrapper<2>(  boost::bind(&SomeStruct::some_method,local[1]) ));
    test(get_wrapper<3>(  boost::bind(&SomeStruct::another_method,local[1]) ));

    test(get_wrapper<4>(  boost::bind(&SomeStruct::some_method,local[2]) ));
    test(get_wrapper<5>(  boost::bind(&SomeStruct::another_method,local[2]) ));
}

It may not require Unique ID's for each invocation, for instance because Functors may already have different types, or runtime scope of their usage do not overlap. But it is safer to use unique ID each time.

Implementation:

live demo

#include <boost/optional.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <ostream>
using namespace std;

template<unsigned ID,typename Functor>
boost::optional<Functor> &get_local()
{
    static boost::optional<Functor> local;
    return local;
}

template<unsigned ID,typename Functor>
typename Functor::result_type wrapper()
{
    return get_local<ID,Functor>().get()();
}

template<typename ReturnType>
struct Func
{
    typedef ReturnType (*type)();
};

template<unsigned ID,typename Functor>
typename Func<typename Functor::result_type>::type get_wrapper(Functor f)
{
    (get_local<ID,Functor>()) = f;
    return wrapper<ID,Functor>;
}

// ----------------------------------------------------------------------

void test(void (*fptr)())
{
    fptr();
}

struct SomeStruct
{
    int data;
    void some_method()
    {
        cout << data << endl;
    }
    void another_method()
    {
        cout << -data << endl;
    }
};

int main()
{
    SomeStruct local[] = { {11}, {22}, {33} };

    test(get_wrapper<0>(  boost::bind(&SomeStruct::some_method,local[0]) ));
    test(get_wrapper<1>(  boost::bind(&SomeStruct::another_method,local[0]) ));

    test(get_wrapper<2>(  boost::bind(&SomeStruct::some_method,local[1]) ));
    test(get_wrapper<3>(  boost::bind(&SomeStruct::another_method,local[1]) ));

    test(get_wrapper<4>(  boost::bind(&SomeStruct::some_method,local[2]) ));
    test(get_wrapper<5>(  boost::bind(&SomeStruct::another_method,local[2]) ));
}


P.S. Beaware of multi-thread access - in such cases you should use some kind of Thread-local storage data.

这篇关于将std :: bind转换为函数指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆