2

I need to pass a non-static member function to a parameter

class Foo {
    void f() {}
    void caller() {
        //calling of g() happens here using f()
    }
};

Class Goo {
    std::map<int,std::vector<std::function<void()>>>> m;
    void g(int i, std::function<void()> const& h) {
        m[i].push_back(h);
    }
}

I tried calling g(f), g(Foo::f), g(std::make_fn(Foo::f), g(std::make_fn(Foo:f, this), g(this.f) and also also tried to pass it as reference (althought it should ).
The error i get is of invalid use of nonstatic member function.

Edit: I added the functionality behind g()

1
  • Please note that you can't store references in containers. If you want references, then use pointers instead. In this case, it doesn't make sense; just store values. Commented Nov 22, 2017 at 10:11

4 Answers 4

2

The problem you have to solve is that this argument is implicit for non-static member function. This means that if you want to call the member function later you need to pass pointer to the object as well.

One of the ways to do this is to use std::bind(&Foo::f, this)

Update 1 You can use smart pointers to tie lifetime of Foo to the lifetime of a functor that is created by the std::bind.

class Foo : std::enable_shared_from_this<Foo> {
    void f() {}
    void caller() {
        // CAVEAT! shared_from_this() will work iff instance of `Foo` is already owned 
        // by an std::shared_ptr. This means that when you create `Foo`
        // you must do so via std::make_shared<Foo>()
        g(std::bind(&Foo::f, shared_from_this()));
    }
};

This is how you can bind lifetime of Foo to the lifetime of the std::function that is produced via std::bind.

Please see the caveat in the code comment though.

Update 2 Your functor vector is incorrect.

std::map<int,std::vector<std::function<void()>const&>> m;

must be

std::map<int,std::vector<std::function<void()>>> m;

(without const reference)

Sign up to request clarification or add additional context in comments.

9 Comments

This solution gave me an entirely new set of errors. The g() actually takes the functions and pushes them into a vector where it stores them to be executed late. It gave me errors about forming reference type and allocator error
@ZergOvermind What are you trying to acheive by that?
Those functions are supposed to be executed whenever given event happens. g() represents the subscribe function and f() is supposed to be the function that for that given object does something with whatever data it will recieve or it will simply record the fact that the event happened. To be more specific i store map of vectors of function where every event has corespinding vector of functions which it then executes.
I added it to the g()
@ZergOvermind there is a solution that involves binding a smart pointer (std::shared_ptr to be precise) instead of this. This will make sure that the instance of Foo is alive so that the function can be executed correctly. But this solution requires Foo to already be under std::shared_ptr ownership, which may or may not feel clumsy, depending on the rest of your architecture.
|
0

Instead of drily passing the function address and hope for correct casts, you can use type-safe Functor pattern to pass functions as arguments.

I.e. declare a class for function f() and put the implementation in operator(). You can use the constructor to preload any kind of function argument, or use the arguments of an overloaded operator(). You can pass the function around like an object, cache values as long as you like, and dispose of any memory when you do no longer need it.

Comments

0

You can utilize lamba to wrap up a member function call:

void g(std::function<void()> const&);

class Foo
{
    void f(void) {}

    void caller(void)
    {
        g
        (
             ::std::function<void (void)>
             {
                  // we need to capture "this" because f is a non-static member function
                  [this](void) -> void
                  {
                      f();
                  }
              }
         );
    }
};

Comments

0

You can bind function with this using std::bind

g( std::bind(&Foo::f, this) );

Here full solution:

#include <functional>
#include <iostream>
void g(std::function<void()> const& func){
        func();
};
class Foo {
public:
    void f() const{std::cout<<"function f()\n";}
    void caller() const {
        //calling of g() happens here using f()
        g( std::bind(&Foo::f, this) );
    }
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.