/*
* This example show some ways of using std::function to call
* a) C-like function
* b) class-member function
* c) operator()
* d) lambda function
*
* Function call can be made:
* a) with right arguments
* b) argumens with different order, types and count
*/
#include <iostream>
#include <functional>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using namespace std::placeholders;
// simple function to be called
double foo_fn(int x, float y, double z)
{
double res = x + y + z;
std::cout << "foo_fn called with arguments: "
<< x << ", " << y << ", " << z
<< " result is : " << res
<< std::endl;
return res;
}
// structure with member function to call
struct foo_struct
{
// member function to call
double foo_fn(int x, float y, double z)
{
double res = x + y + z;
std::cout << "foo_struct::foo_fn called with arguments: "
<< x << ", " << y << ", " << z
<< " result is : " << res
<< std::endl;
return res;
}
// this member function has different signature - but it can be used too
// please not that argument order is changed too
double foo_fn_4(int x, double z, float y, long xx)
{
double res = x + y + z + xx;
std::cout << "foo_struct::foo_fn_4 called with arguments: "
<< x << ", " << z << ", " << y << ", " << xx
<< " result is : " << res
<< std::endl;
return res;
}
// overloaded operator() makes whole object to be callable
double operator()(int x, float y, double z)
{
double res = x + y + z;
std::cout << "foo_struct::operator() called with arguments: "
<< x << ", " << y << ", " << z
<< " result is : " << res
<< std::endl;
return res;
}
};
int main(void)
{
// typedefs
using function_type = std::function<double(int, float, double)>;
// foo_struct instance
foo_struct fs;
// here we will store all binded functions
std::vector<function_type> bindings;
// var #1 - you can use simple function
function_type var1 = foo_fn;
bindings.push_back(var1);
// var #2 - you can use member function
function_type var2 = std::bind(&foo_struct::foo_fn, fs, _1, _2, _3);
bindings.push_back(var2);
// var #3 - you can use member function with different signature
// foo_fn_4 has different count of arguments and types
function_type var3 = std::bind(&foo_struct::foo_fn_4, fs, _1, _3, _2, 0l);
bindings.push_back(var3);
// var #4 - you can use object with overloaded operator()
function_type var4 = fs;
bindings.push_back(var4);
// var #5 - you can use lambda function
function_type var5 = [](int x, float y, double z)
{
double res = x + y + z;
std::cout << "lambda called with arguments: "
<< x << ", " << y << ", " << z
<< " result is : " << res
<< std::endl;
return res;
};
bindings.push_back(var5);
std::cout << "Test stored functions with arguments: x = 1, y = 2, z = 3"
<< std::endl;
for (auto f : bindings)
f(1, 2, 3);
}