convert std::bind to function pointer

后端 未结 4 602
别那么骄傲
别那么骄傲 2020-11-28 09:13

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*, i         


        
4条回答
  •  萌比男神i
    2020-11-28 09:37

    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 
    #include 
    #include 
    #include 
    using namespace std;
    
    template
    boost::optional &get_local()
    {
        static boost::optional local;
        return local;
    }
    
    template
    typename Functor::result_type wrapper()
    {
        return get_local().get()();
    }
    
    template
    struct Func
    {
        typedef ReturnType (*type)();
    };
    
    template
    typename Func::type get_wrapper(Functor f)
    {
        (get_local()) = f;
        return wrapper;
    }
    
    // ----------------------------------------------------------------------
    
    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.

提交回复
热议问题