How do i write a pointer-to-member-function with std::function?

前端 未结 5 1113
刺人心
刺人心 2020-12-07 15:58

I know how to declare int fn(double) inside of std::function (std::function). I know how to write a pointer-to-member-function (

相关标签:
5条回答
  • 2020-12-07 16:20

    If you can use Boost then you can use Boost.Bind. It's easily accomplished like this:

    boost::bind(&MyClass::MemberFunction, pInstance, _1, _2)
    

    Hopefully it's fairly self-explanatory. _1 and _2 are placeholders for parameters you can pass through to the function.

    0 讨论(0)
  • 2020-12-07 16:28

    A member function is not a function. It is not itself anything you can call. All you can do is call a member function of an instance object. Only the pair of pointer-to-member-function and object constitutes a callable entity.

    To bind an instance to a PTMF and obtain something callable, use bind:

    #include <functional>
    
    struct Foo
    {
        double bar(bool, char);
    };
    
    Foo x;
    using namespace std::placeholders;
    std::function<double(bool, char)> f = std::bind(&Foo::bar, x, _1, _2);
    f(true, 'a'); //...
    

    As with lambdas, bind expressions have an unknowable type, and the conversion to std::function (as well as the actual dispatch) is potentially expensive. If possible, it is preferable to use auto for the type of the bind expression.

    0 讨论(0)
  • 2020-12-07 16:28

    One of the guidelines in Scott Meyer's Modern C++11 book is to avoid std::bind and always use a lambda closure instead:

    struct A{ int fn(double){ return 0; } };
    
    std::function<int(double)> f = [a = A{}](double x) mutable { return a.fn(x); };
    

    The mutable is necessary here, as the capture a might potentially be changed by the function call (since A::fn is non-const).

    0 讨论(0)
  • 2020-12-07 16:37

    You can use std::binder1st to bind member function to a class instance:

    typedef std::binder1st<std::mem_fun1_t<int, A, double>> MemFn;
    
    void Test(A* a, double d)
    {
       MemFn fn(std::mem_fun(&A::fn), a);
       int nRetVal = fn(d);
    }
    
    int main()
    {
       Test(new A, 1.2f);
       return 0;
    }
    
    0 讨论(0)
  • 2020-12-07 16:41

    std::function is perfectly capable of storing a member function pointer directly. However, you have to adjust the argument list appropriately. Member pointers must be called with an instance of the type (or a derived type). When putting them in a std::function, the first argument in the argument list is expected to be a pointer (or reference or smart-pointer) to the object type.

    So, if I have the following class:

    struct Type
    {
    public:
        int Foo();
    };
    

    The correct syntax to store this member function in a std::function is:

    std::function<int(Type&)> fooCaller = &Type::Foo;
    

    If you want to preserve the argument list (in your case, int(double)), then you need to provide the instance outside of the function. This can be done via std::bind:

    struct A{ int fn(double){ return 0; } };
    
    A anInstance;
    std::function<int(double)> fnCaller = std::bind(&A::fn, &anInstance, std::placeholders::_1);
    

    Note that it is your responsibility to ensure that the object pointer you provide to std::bind remains alive so long as fnCaller is alive. If you return fnCaller to someone, and it has a pointer to a stack object, you're in trouble.

    What's nice is that you could bind a shared_ptr (or any copyable smart pointer) as your object, thanks to how the function call mechanism is defined:

    struct A{ int fn(double){ return 0; } };
    
    auto anInstance = std::make_shared<A>();
    std::function<int(double)> fnCaller = std::bind(&A::fn, anInstance, std::placeholders::_1);
    

    Now you don't have to worry; the binder will continue to keep the object alive, since it stores a shared_ptr by value.

    0 讨论(0)
提交回复
热议问题