Can I store bound functions in a container? - c++

Consider the following code:
void func_0()
{
std::cout << "Zero parameter function" << std::endl;
}
void func_1(int i)
{
std::cout << "One parameter function [" << i << "]" << std::endl;
}
void func_2(int i, std::string s)
{
std::cout << "One parameter function [" << i << ", " << s << "]" << std::endl;
}
int main()
{
auto f0 = boost::bind(func_0);
auto f1 = boost::bind(func_1,10);
auto f2 = boost::bind(func_2,20,"test");
f0();
f1();
f2();
}
The above code works as intended. Is there any way I can store f0, f1, f2 in a container and execute it like this:
Container cont; // stores all the bound functions.
for(auto func : cont)
{
func();
}

Will this example work for you?
std::vector<std::function<void()>> container{f0, f1, f2};
for (auto& func : container)
{
func();
}
You can read here about std::function:
Instances of std::function can store, copy, and invoke any Callable
target ...
So the template argument for this class template (void() in our case) is merely the signature of the Callable. What bind() returned in all your calls to it is exactly a Callable of the form void().

std::bind is not guaranteed to return the same type for functions with the same final interface (final = after binding). So, no, you won't be able to store functions bound with std::bind in a container. You will have to use some sort of type-erasure technique to bring them all to the same type, like std::function. A container of std::function<void()> will be able to store your bound functions (at the expense of type-erasure-related overhead).
I don't know whether it applies to boost::bind, but I suspect it is the same as std::bind in that regard.

Related

Is it possilbe to get a pointer to a generic lambda explicit instantiation?

Is it possible to get a (member) function pointer to a specific instantiation of a generic lambda?
I know I can do so for standard non capturing lambdas, and for abbreviated templates, but I can't seem to be able to get a member function pointer for the explicitly instantiated operator() call operator member function of the invented type for the generic lambda.
#include <iostream>
void f1( auto v) { std::cout << v << std::endl; }
int main() {
void (*pf)(int) = f1<int>; // OK
void (*pf2)(int) = [](int v) { std::cout << v << std::endl; } ; // OK
[](auto v) { std::cout << v << std::endl; }.operator() < int > (42); // OK
auto generic_template = [](auto v) { std::cout << v << std::endl; } ;
using generic_type = decltype (generic_template);
// void (generic_type::*pf3)(int) = &generic_type::operator()<int>; // fails to compile
pf(5);
}
The interest here is academic.
Edit:
As a note of interest to future readers the solutions offered to this question also apply to getting function pointers for lambdas with capture, in addition to generic lambdas. For example, based on the answers :
auto generic_lambda = [](auto v) { std::cout << v << std::endl; } ;
using generic_type = decltype (generic_lambda);
void (generic_type::*pf1)(int) const = &generic_type::operator();
(&generic_lambda->*pf1)(43); // OK
int x = 5;
auto capturing_lambda = [x](int v) { std::cout << v+x << std::endl; } ;
using capturing_type = decltype (capturing_lambda);
void (capturing_type::*pf2)(int) const = &capturing_type::operator();
(&capturing_lambda->*pf2)(43); // OK
Yes, and you can omit the template arguments if they can be deduced from the type being initialized (or the result type of a cast) but since the lambda isn’t mutable the member function is const and so must be the pointer-to-member.
Is it possible to get a (member) function pointer to a specific
instantiation of a generic lambda?
Lambda's operator() is const-qualified by default, you need to add const to the member function pointer type
void (generic_type::*pf3)(int) const = &generic_type::operator();
And since pf3 is a member function pointer, please note that it need a specific lambda object and uses .* or ->* to invoke.
(generic_template.*pf3)(42);
Demo

What is the advantage of storing a lambda in a `std::function` as opposed to an `auto variable`?

What is the advantage of storing a lambda in a std::function as opposed to an auto variable. For example in the code below I store the lambda in variable f1 rather than in std::function f.
#include <iostream>
#include <functional>
using namespace std;
void global_f() {
cout << "global_f()" << endl;
}
struct Functor {
void operator()() { cout << "Functor" << endl; }
};
int main() {
std::function<void()> f;
cout << "sizeof(f) == " << sizeof(f) << endl;
f = global_f;
f();
auto f1 = [](){ cout << "Lambda" << endl;};
f1();
Functor functor;
f = functor;
f();
}
In your simple example, there is no advantage to storing the lambda inside a std::function. Often, storing a lambda using auto is more efficient, but it also highly restrictive. The auto version can serve only as a local variable. If you want to store the lambda for later use, then you must use a std::function.
For example, you might want to store the lambda inside a class member. Consider the following class:
class Foo
{
std::function<void()> callback_;
public:
void Bar(int value)
{
callback_ = [value] { DoStuff(value); }
}
/* other constructors and methods omitted */
}
In this case, you can't use auto because the lambda's type is anonymous and only available within the Bar method.
std::function is also useful when you want to use lambdas as arguments to regular functions. The function has no way to know the lambda's type, but it can declare a std::function parameter instead. For example:
void Foo(std::function<void()> callback);
...
Foo([](){ cout << "Lambda" << endl;});
It's worth pointing out that this does not apply to function templates. When using a lambda in such a context, it's usually a better idea to let the compiler deduce the lambda's type (similar to using auto). For example:
template <class F> void Foo(F&& callback) { /* details */ }
...
Foo([](){ cout << "Lambda" << endl;}

How does a std::function object which return a std::function work when call by operator()?

Sample:
#include "stdafx.h"
#include <functional>
#include <iostream>
#include <string>
std::function<void(int)> Foo()
{
int v = 1;
int r = 2;
auto l = [v, r](int i)
{
std::cout << v << " " << r << " " << i << std::endl;
};
return l;
}
int main()
{
auto func = Foo();
func(3);
return 0;
}
Why func(3) can pass 3 to i which is the formal argument of the lambda in Foo(). I can't think out. thanks.
TL;DR: You don't pass your argument 3 into a function Foo. You pass it to a method of an object func.
A bit more detailed explanation is below.
First of all, I would like to clarify what a lambda is. A lambda in C++ is nothing more than an anonymous functor class, so essentially just a syntactic sugar. A closure is an instance of a lambda type. However, quite often you can hear words "lambda" and "closure" being used interchangeably.
So within your function Foo() you create a closure object l
auto l = [v, r](int i)
{
std::cout << v << " " << r << " " << i << std::endl;
};
which would be technically equivalent to this code:
struct Functor
{
Functor(int v, int r) : v_(v), r_(r) {}
void operator ()(int i) const {
std::cout << v_ << " " << r_ << " " << i << std::endl;
}
private:
int v_;
int r_;
};
Functor l(v, r);
Now, on the next line you return an std::function object.
return l; // actually creates std::function<void(int)>(l) and returns it
So in your main function a func is just an object which stores copies of values v, r obtained during a call to Foo() and defines operator(), similar to the struct above.
Therefore, calling func(3) you actually invoke an object method on a concrete object func, and without syntactic sugar it looks like func.operator()(3).
Here's a live example to illustrate my point.
Hope that helps to resolve your confusion.

Passing method to method in c++

I have faced with a problem of passing method to method in C++. What I am trying to do is to reduce amount of code, which is almost the same for several methods.
For example, I have next code:
class F_test {
public:
void f1() {
std::cout << "f1" << std::endl;
}
void f2() {
std::cout << "f2" << std::endl;
}
void foo_main(std::string str, std::function<void(void)> const &f) {
std::cout << "some actions before" << std::endl;
std::cout << str << std::endl;
f();
std::cout << "some actions after" << std::endl;
}
void f1(std::string s1) {
std::function <void(void)> m1 = F_test::f1;
foo_main("processing f1", m1);
}
void f2(std::string s2) {
std::function <void(void)> m2 = F_test::f2;
foo_main("processing f2", m2);
}
};
As for processing f1 and f2 methods I need to perform some the same operations, I have decided to created one method (foo_main) with these operations and pass needed function (f1 or f2) to it, rather than create two separate methods with code duplication.
But, these code is failed on compilation with:
'F_test::f1': function call missing argument list; use '&F_test::f1' to create a pointer to member
'F_test::f2': function call missing argument list; use '&F_test::f2' to create a pointer to member
If to write &F_test::f1 and &F_test::f2, another compilation error is happened:
'void std::_Func_class<_Ret,>::_Set(std::_Func_base<_Ret,> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,> *'
Non-static member functions need an object to be called with. You can't just call f1() without an instance of F_test. The compile error results from you trying to do that.
To create a null ary function out of member function, you need to bind an instance to it, whether via std::bind:
std::function <void()> m1 = std::bind(&F_test::f1, this);
or a lambda:
std::function <void()> m1 = [this]{ f1(); };
Note that bind doesn't work in this case since you have overloaded the name f1. It would work in the general case though. The lambda will work regardless.
The simpler would be to use lambda:
F_test test;
test.foo_process("string", [&](){test.f1();});
Else to select (in std::bind) overload f1() whereas other overloads exist (as f1(std::string)), you have to specify which one you want:
static_cast<void (F_test::*)()>(&F_test::f1)
If you don't want to use lambda by some reasons, then you should rewrite the code like:
class F_test {
public:
void f1impl() const {
std::cout << "f1" << std::endl;
}
void f2impl() const {
std::cout << "f2" << std::endl;
}
void foo_process(std::string str, std::function<void(const F_test&)> const &f) {
std::cout << "some actions before" << std::endl;
std::cout << str << std::endl;
f(*this);
std::cout << "some actions after" << std::endl;
}
void f1(std::string s1) {
std::function<void(const F_test&)> f = &F_test::f1impl;
foo_process("processing f1", f);
}
void f2(std::string s2) {
std::function <void(const F_test&)> m2 = &F_test::f2impl;
foo_process("processing f2", m2);
}
};
you can't use a member function pointer to initialize a std::function. Use a lambda instead.
void f1(std::string s1) {
auto m1 = [this](){ f1(); };
foo_main("processing f1", m1);
}

Call a std::function class member with std::mem_fn

My plan is to build several listener classes which own predefined "callback hooks".
In the example below class Foo has a "callback hook" called onChange. It will be set to a default callback function during construction. It can also be set to an arbitrary function which provides the correct interface, like shown with the object f1 and the function callback().
The problem is when I want to call the object member onChange inside the for-loop the compiler says that I provide to much arguments. i am aware of the problem that i don't provide a member function to the std::mem_fn but instead an object member which is a function wrapper.
How do I manage to pass the argument to the std::function member object of class Foo without using std::bind and use std::mem_fn instead like shown in the example?
struct Foo
{
Foo()
{
// default callback
onChange = [](int value)
-> void { std::cerr << "Foo::onChange( " << value << " )" << std::endl; };
}
// class destructor
virtual ~Foo() {}
std::function<void(int value)> onChange;
};
void callback(int value)
{
std::cerr << "callback( " << value << " )" << std::endl;
}
int main()
{
Foo f0;
Foo f1;
f1.onChange = callback;
auto vec = std::vector<Foo>();
vec.push_back(f0);
vec.push_back(f1);
auto func_wrapper = std::mem_fn( &Foo::onChange );
for (auto f : vec)
{
func_wrapper(f, 42);
}
}