Using Generic Std::Function Objects With Member Functions in One Class

Using generic std::function objects with member functions in one class

A non-static member function must be called with an object. That is, it always implicitly passes "this" pointer as its argument.

Because your std::function signature specifies that your function doesn't take any arguments (<void(void)>), you must bind the first (and the only) argument.

std::function<void(void)> f = std::bind(&Foo::doSomething, this);

If you want to bind a function with parameters, you need to specify placeholders:

using namespace std::placeholders;
std::function<void(int,int)> f = std::bind(&Foo::doSomethingArgs, this, std::placeholders::_1, std::placeholders::_2);

Or, if your compiler supports C++11 lambdas:

std::function<void(int,int)> f = [=](int a, int b) {
this->doSomethingArgs(a, b);
}

(I don't have a C++11 capable compiler at hand right now, so I can't check this one.)

How to initialize `std::function` with a member-function?

print_add is a non-static member function of foo, which means it must be invoked on an instance of Foo; hence it has an implicit first argument, the this pointer.

Use a lambda that captures the foo instance and invokes print_add on it.

Foo foo;
test([&foo](int i){ foo.print_add(i); });

Another option is to use std::bind to bind the foo instance:

test(std::bind(&Foo::print_add, &foo, std::placeholders::_1));

Live demo

std::function to member function

Funcp func = 
std::bind(&A::func, &a, std::placeholders::_1, std::placeholders::_2);

Array of generic member functions of base class

I think you’d need something akin std::mem_fn() but with the added flexibility of converting the object pointer. That should be straight forward to create:

template <typename R, typename X>
class open_mem_fun {
R (X::*fn)();
public:
open_mem_fun(R (X::*fn)()): fn(fn) {}
template <typename T>
R operator()(T* p) const {
return (dynamic_cast<X&>(*p).*fn)();
}
};
template <typename R, typename X>
open_mem_fun<R, X> open_mem_fn(R (X::*fn)()) {
return open_mem_fun<R, X>(fn);
}

The resulting objects should be callable via a suitable std::function object:

std::function<void(Base*)>(open_mem_fn(&X::XFunc));

C++14: Generic lambda with generic std::function as class member

There is no way you'll be able to choose between two generic lambdas at run-time, as you don't have a concrete signature to type-erase.

If you can make the decision at compile-time, you can templatize the class itself:

template <typename F>
class SomeClass
{
private:
F fooCall;

public:
SomeClass(F&& f) : fooCall{std::move(f)} { }
};

You can then create an helper function to deduce F:

auto makeSomeClassImpl(std::true_type) 
{
auto l = [](auto a){ cout << a.sayHello(); };
return SomeClass<decltype(l)>{std::move(l)};
}

auto makeSomeClassImpl(std::false_type)
{
auto l = [](auto b){ cout << b.sayHello(); };
return SomeClass<decltype(l)>{std::move(l)};
}

template <bool B>
auto makeSomeClass()
{
return makeSomeClassImpl(std::bool_constant<B>{});
}

Question about std::function when using with static member function

For regular functions (and so static method), inherited syntax from C allows both f and &f as function pointer.

Both function pointer, and result of std::bind are callable, and so valid argument to std::function (and as first argument of std::bind).

Pass non-static member function to member function of another class

As explained here, pass a lambda that calls the function on the enclosing A instance:

mB->dopristep([&] (int a, int b) { return g(a, b); }, T, h);

Additionally, you could modify dopristep to accept a functional which will avoid some overhead:

template <typename F>
int dopristep(F&& f, double t, double h);

Call any object member function on a list of objects using std::function

void CMyService::ApplyToList(void (CMyListItem::*func)(double), double myValue) {
for (auto p : myList) {
(p->*func)(myValue);
}
}

With pre-C++11 compilers:

void CMyService::ApplyToList(void (CMyListItem::*func)(double), double myValue) {
for (std::list<CMyListItem*>::iterator v_Iter = myList.begin();
v_Iter != myList.end(); ++v_Iter) {
((*v_Iter)->*func)(myValue);
}
}

how to create templated-like namespace for member functions

Since you want some input data to stay longer than a single function call, unless it's fully compile-time data a runtime state is inevitable. The question is how you want this data to be encapsulated - different approaches will yield very different (subjective) feelings of how convenient they are.

Based on your usage example:

this->fun1 = foo<a,b>::bar;

If you want to avoid state (or rather encapsulate it) you can create a factory that will create functions for you:

std::function<int(int)> make_func(int a, int b)
{
return [=](int x){ return actual_function(a, b, x); };
}

this->fun1 = make_func(a, b); // now std::function will hold lambda's captured state

This topic is generally known as partial application and I guess boost or other libraries already have a lot of supporting code for such manipulations.



Related Topics



Leave a reply



Submit