4

This is my stripped-down program, where I'm trying to use function variables to modify class functionality at run time. So - I declare a member variable m_func using the std::function template and a function myFunc with compatible signature:

#include <functional>
#include <iostream>

struct T
{
  T():m_func([](int){return true;}) {}
  void assign() {m_func = &T::myFunc;}    // <======== Problem is here
  void call(int M) const {std::cout << m_func(M) << std::endl;}
private:
  bool myFunc(int N) {return (N >= 4);}
  using func = std::function<bool(int)>;
  func m_func;
};

int main()
{
  T t;
  t.assign();
  t.call(6);
}

However, the compiler (g++ 4.8.4 with -std=c++11 option) gives me an error with long output, saying that template argument deduction/substitution failed and a lot more...

Why can't I assign the myFunc function to the m_func variable?

0

4 Answers 4

5

A non-static member function pointer cannot be assigned to std::function directly. The general solution for this problem is to bundle the this pointer into a lambda like this :

void assign() { 
    m_func = [this](int N) { 
        return this->myFunc(N); 
    };
}

In your case, it seems simpler to just make myFunc static.

struct T
{
    T() :m_func([](int) {return true; }) {}
    void assign() { m_func = &T::myFunc; }
    void call(int M) const { std::cout << m_func(M) << std::endl; }
private:
    static bool myFunc(int N) { return (N >= 4); }
//  ^^^^^^ static methods can be assigned to std::function directly
    using func = std::function<bool(int)>;
    func m_func;
};
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I can't make the myFunc static, cause in reality it needs to access a bunch of member variables
4

If you want the member function to be called on the current object, then you want:

m_func = std::bind(&T::myFunc, this, std::placeholders::_1);

2 Comments

I think you're missing a placeholder.
@RichardJ.RossIII: I did indeed, thanks!
2
void assign() {m_func = &T::myFunc;}

Member function pointers have an implicit this pointer that needs to be passed as the first argument in their signature. Either use std::bind to bind that first,

void assign() {
    m_func = std::bind(&T::myFunc, this, std::placeholders::_1);
}

or use a lambda-expression (capturing this).

void assign() {
    m_func = [this](int arg){ return this->myFunc(arg); };
}

Comments

1

As mentioned by @Kerrek SB above, you could use std::bind.

However, it's better to use a lambda since it can have less overhead :

m_func = [this] (int N) {return myFunc(N);};

2 Comments

As for the overhead - do you mean overhead during this assignment, or the overhead during the m_func call? (I care about the second case actually)
Actually I'd say both of them.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.