C++ std::function variable with varying arguments - c++

In my callback system I want to store std::function (or something else) with varying arguments.
Example:
I want to call void()
I want to call void(int, int)
I want 1) and 2) to be stored in the same variable and choose what to call in actuall call
FunctionPointer f0;
FunctionPointer f2;
f0();
f2(4, 5);
Is it possible to do something like this? Or I have to create several "FuntionPointer" templates based on input arguments count.
EDIT
Is it possible to utilize std::bind somehow for this task? With std::bind I can have std::function<void()> f = std::bind(test, 2, 5);
EDIT 2
Practical use case: I have a trigger system and I want to assign funtion pointers to actions, so when action happen, function is called.
Pseudo-code sample:
structure Trigger
{
Function f;
}
Init:
Trigger0.f = pointer to some function ()
Trigger1.f = pointer to some function (a, b)
Input:
Find Trigger by input
if (in == A) Trigger.f();
else Trigger.f(10, 20)
or if possible
Input:
Find Trigger by input
if (in == A) f = bind(Trigger.f);
else f = bind(Trigger.f, 10, 20);
f()

std::function<void()> and std::function<void(int, int)> are two absolutely distinct types. You need some sort of union functionality (or polymorphism) to store an object of an unknown type.
If you can use Boost, you could easily do this with boost::variant:
// Declaration:
boost::variant<std::function<void()>, std::function<void(int, int)> > f;
// Calling, explicit:
if (fContainsNullary()) {
boost::get<std::function<void()>>(f)();
} else {
boost::get<std::function<void(int, int)>>(f)(4, 5);
}
It is up to you to provide the logic of fContainsNullary(). Alternatively, you can use the variant's own stored knowledge of value type by using a visitor:
struct MyVisitor : boost::static_visitor<void>
{
result_type operator() (const std::function<void()> &a) {
a();
}
result_type operator() (const std::function<void(int, int)> &a) {
a(4, 5);
}
};
// Calling, via visitor:
boost::apply_visitor(MyVisitor(), f);
If Boost is not an option, you can hand-craft a suitable union for much the same purpose.

The following solution might work for you (I'm not sure that the code is absolutely correct here):
Create a wrapper for std::function with virtual destructor to enable using dynamic cast
class function_wrapper_base
{
virtual ~function_wrapper_base();
}
template <class... Args>
class function_wrapper
: public function_wrapper_base
{
public:
std::function<void, Args...> f;
...
};
Then create a class variant_function_holder
class variant_function_holder
{
std::unique_ptr<function_wrapper_base> f;
...
template <class... Args>
void operator()(Args&&... args)
{
function_wrapper<std::decay<Args>::type...> * g = dynamic_cast<function_wrapper<std::decay<Args>::type...>>(f.get());
if (g == nullptr)
{
// ToDo
}
g->f(std::forward<Args>(args)...);
}
};

Well, if you can use RTTI, you can define a MultiFuncObject like this, and you can easily bind other functions. Also, you can easily call them. But unfortunately, this approach only works for a limited number of arguments. But actually boost::bind also supports limited number of arguments (by default 9). So you can extend this class to satisfy your needs.
Before giving you the source of MultiFuncObject, I want to show you how you can use it. It takes an template argument to be used as return type. You can bind new functions with += operator. With some template magic, the class distinguishes differences between bound functions with same count of arguments with at least one different argument type.
You need C++11, because MultiFuncObject uses std::unordered_map and std::type_index.
Here is usage:
#include <iostream>
using namespace std;
void _1() {
cout << "_1" << endl;
}
void _2(char x) {
cout << "_2" << " " << x << endl;
}
void _3(int x) {
cout << "_3" << " " << x << endl;
}
void _4(double x) {
cout << "_4" << " " << x << endl;
}
void _5(int a, int b) {
cout << "_5" << " " << a << " " << b << endl;
}
void _6(char a, int b) {
cout << "_6" << " " << a << " " << b << endl;
}
void _7(int a, int b, int c) {
cout << "_7" << " " << a << " " << b << " " << c << endl;
}
int main() {
MultiFuncObject<void> funcs;
funcs += &_1;
funcs += &_2;
funcs += &_3;
funcs += &_4;
funcs += &_5;
funcs += &_6;
funcs += &_7;
funcs();
funcs('a');
funcs(56);
funcs(5.5);
funcs(2, 5);
funcs('q', 6);
funcs(1, 2, 3);
return 0;
}
I hope this is close to what you want. Here is the source of MultiFuncObject:
#include <typeinfo>
#include <typeindex>
#include <unordered_map>
using namespace std;
template <typename R>
class MultiFuncObject {
unordered_map<type_index, void (*)()> m_funcs;
public:
MultiFuncObject<R> operator +=( R (* f)() ) {
m_funcs[typeid( R() )] = (void (*)()) f;
return *this;
}
template <typename A1>
MultiFuncObject<R> operator +=( R (* f)(A1) ) {
m_funcs[typeid( R(A1) )] = (void (*)()) f;
return *this;
}
template <typename A1, typename A2>
MultiFuncObject<R> operator +=( R (* f)(A1, A2) ) {
m_funcs[typeid( R(A1, A2) )] = (void (*)()) f;
return *this;
}
template <typename A1, typename A2, typename A3>
MultiFuncObject<R> operator +=( R (* f)(A1, A2, A3) ) {
m_funcs[typeid( R(A1, A2, A3) )] = (void (*)()) f;
return *this;
}
R operator()() const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R() ));
if (it != m_funcs.end()) {
R (*f)() = ( R (*)() )(it->second);
(*f)();
}
}
template <typename A1>
R operator()(A1 a1) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1) ));
if (it != m_funcs.end()) {
R (*f)(A1) = ( R (*)(A1) )(it->second);
(*f)(a1);
}
}
template <typename A1, typename A2>
R operator()(A1 a1, A2 a2) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1, A2) ));
if (it != m_funcs.end()) {
R (*f)(A1, A2) = ( R (*)(A1, A2) )(it->second);
(*f)(a1, a2);
}
}
template <typename A1, typename A2, typename A3>
R operator()(A1 a1, A2 a2, A3 a3) const
{
unordered_map<type_index, void (*)()>::const_iterator it = m_funcs.find(typeid( R(A1, A2, A3) ));
if (it != m_funcs.end()) {
R (*f)(A1, A2, A3) = ( R (*)(A1, A2, A3) )(it->second);
(*f)(a1, a2, a3);
}
}
};
It stores different function prototypes using std::unordered_map with keys of std::type_index and values of void (*)(). When needed, the correct function is retrieved using that map.
Here is the working example

C++11 to the rescue!
If you can generalize your function to a functor object taking no arguments, then you can call it with any lambda.
#include <iostream>
using namespace std;
template <class F>
void call_it(F&& f)
{
f();
}
int main()
{
int x = 50, y = 75;
call_it([] () { cout << "Hello!\n"; });
call_it([x,y] () { cout << x << " + " << y << " = " << x + y << '\n';});
return 0;
}

If std::function is not necessary for you, you can create a proxy class.
class fn_t {
public:
typedef void (*fn_1_t)();
typedef void (*fn_2_t)(int, int);
fn_1_t fn_1;
fn_2_t fn_2;
fn_t operator=(fn_1_t func_1) { fn_1 = func_1; return *this; }
fn_t operator=(fn_2_t func_2) { fn_2 = func_2; return *this; }
void operator()() { (*fn_1)(); }
void operator()(int a, int b) { (*fn_2)(a, b); }
};
#include <iostream>
using namespace std;
void first() {
cout << "first" << endl;
}
void second(int a, int b) {
cout << "second " << a << " : " << b << endl;
}
int main() {
fn_t f;
f = &first;
f = &second;
f();
f(5, 4);
return 0;
}
Class fn_t automatically works with two prototypes you want, assigns automatically needed one, and it can call functions with both prototypes by overlading () operator with appropriate parameters.
You may want to check for validity of function pointers fn_1 and fn_2 but I didn't include this checking for minimality.
The advantage of this is that you only need C++ and not even STL and Boost.

The other answers are fine but I want to show my solution as well.
It's a small header with which you can "elongate" function signatures.
This allows you to do this (extract from the github example):
int foo_1p(int a);
int foo_2p(int a, int b);
int foo_3p(int a, int b, int c);
int foo_4p(int a, int b, int c, int d);
int foo_5p(int a, int b, int c, int d, int e);
int foo_6p(int a, int b, int c, int d, int e, int f);
int foo_7p(int a, int b, int c, int d, int e, int f, std::string g);
...
int main()
{
std::unordered_map<std::string, std::function<int(int, int, int, int, int, int, std::string)>> map;
map["foo_1p"] = ex::bind(foo_1p, ph, ph, ph, ph, ph, ph);
map["foo_2p"] = ex::bind(foo_2p, ph, ph, ph, ph, ph);
map["foo_3p"] = ex::bind(foo_3p, ph, ph, ph, ph);
map["foo_4p"] = ex::bind(foo_4p, ph, ph, ph);
map["foo_5p"] = ex::bind(foo_5p, ph, ph);
map["foo_6p"] = ex::bind(foo_6p, ph);
map["foo_7p"] = foo_7p;
for (const auto& f : map)
{
std::cout << f.first << " = " << f.second(1, 1, 1, 1, 1, 1, "101") << std::endl;
}
}

Related

Can I give different behaviours to boost::proto::tag types?

I am trying to use boost proto to lazily evaluate expressions, what I want to do is be able to give different behaviours to tags like +, -, function etc.
function(
terminal(8functionILi2EE)
, plus(
multiplies(
terminal(6tensorILi0EE)
, terminal(6tensorILi1EE)
)
, multiplies(
terminal(6tensorILi2EE)
, terminal(6tensorILi3EE)
)
)
)
For a tree like above, I want to be able to specify how each of the tree nodes should behave.
For eg.
struct context : proto::callable_context< context const >
{
// Values to replace the tensors
std::vector<double> args;
// Define the result type of the zero.
// (This makes the zero_context "callable".)
typedef double result_type;
// Handle the tensors:
template<int I>
double operator()(proto::tag::terminal, tensor<I>) const
{
std::cout << this->args[I] << std::endl;
return this->args[I];
}
template<int I>
void operator()(proto::tag::plus) const
{
std::cout << " + " << std::endl;
}
};
When I do
double result = (_tensorA + _tensorB)(10, 20);
I expect my output to be
10
+
20
But it's just
10
20
Any help would be deeply appreciated! :)
template<int I>
void operator()(proto::tag::plus) const
{
std::cout << " + " << std::endl;
}
The template argument I is non-deducible, so the overload will never be applicable. Drop the template argument:
void operator()(proto::tag::plus) const
{
std::cout << " + " << std::endl;
}
HOWEVER What you really want is intercept the binary operator. Well. Note it's binary. So it has two args:
template<size_t I, size_t J>
void operator()(proto::tag::plus, proto::literal<tensor<I>>&, proto::literal<tensor<J>>&) const {
std::cout << " + " << std::endl;
}
Live On Coliru
However, this blocks further evaluation of the expression tree. Not what you wanted, right. So, let's do a simplisitic re-implementation:
template<size_t I, size_t J>
double operator()(proto::tag::plus, proto::literal<tensor<I>>& a, proto::literal<tensor<J>>& b) const {
auto va = (*this)(proto::tag::terminal{}, a.get());
std::cout << " + " << std::endl;
auto vb = (*this)(proto::tag::terminal{}, b.get());
return va + vb;
}
Live On Coliru
Generic, please
However, something tells me you wanted generic expressions. So t1 + (t2 + t3) should also work, but (t2 + t3) is no literal...
Let's simplify by delegating:
template<typename A, typename B>
double operator()(proto::tag::plus, A& a, A& b) const {
auto va = proto::eval(a, *this);
std::cout << " + " << std::endl;
auto vb = proto::eval(b, *this);
return va + vb;
}
Full Sample
Live On Coliru
#include <boost/proto/proto.hpp>
#include <vector>
namespace proto = boost::proto;
template <size_t N> struct tensor { };
template <size_t N, size_t M> tensor<N+M> operator+(tensor<N>, tensor<M>) { return {}; }
struct context : proto::callable_context< context const >
{
using base_type = proto::callable_context<context const>;
// Values to replace the tensors
std::vector<double> args { 0, 111, 222, 333 };
// Define the result type of the zero.
// (This makes the zero_context "callable".)
typedef double result_type;
// Handle the tensors:
template<size_t I>
double operator()(proto::tag::terminal, tensor<I>) const
{
std::cout << this->args[I] << std::endl;
return this->args[I];
}
template<typename A, typename B>
double operator()(proto::tag::plus, A& a, B& b) const {
auto va = proto::eval(a, *this);
std::cout << " + " << std::endl;
auto vb = proto::eval(b, *this);
return va + vb;
}
};
int main() {
proto::literal<tensor<1> > t1;
proto::literal<tensor<2> > t2;
proto::literal<tensor<3> > t3;
auto r = proto::eval(t1 + (t2 + t3), context());
std::cout << "eval(t1 + (t2 + t3)) = " << r << "\n";
}
Prints
111
+
222
+
333
eval(t1 + (t2 + t3)) = 666

runtime specialization of overloaded function

This is a variant of this SO question. I have an overloaded function that takes parameters of different types and returns different types:
struct mystruct {
auto f (int x, int y) -> int;
auto f (std::string x, int y) -> float;
};
The function f needs to call itself with one of its parameters specialized a number of times.
I'd like to define a function that specializes the parameter y, that is I'd want g(z) = f(z,y). The return type of g and the type of its unique parameter z variable, but the implementation is the same in both cases.
The best implementation I could find of this situation is overloading the lambda function:
template <class F1, class F2>
struct overload_set : F1, F2
{
overload_set(F1 f1, F2 f2) : F1(f1), F2(f2) {}
using F1::operator();
using F2::operator();
};
template <class F1, class F2>
overload_set<F1, F2> overload(F1 f1, F2 f2) {
return overload_set<F1, F2>(f1, f2);
};
struct mystruct {
auto f( std::string x, int y) -> float {
return y+9.3;
}
auto f( int x, int y) -> int
{
auto g = overload (
[=]( int z ) -> int {return f(z,y);},
[=]( std::string z) -> float { return f(z,y); }
);
if ( x == 0 ) {
std::cout << g("this string") << "\n";
return 0;
}
if ( x == 1 ) return y;
return 7;
}
};
int main () {
mystruct h;
std::cout << h.f(1,4) << "\n";
std::cout << h.f(0,2) << "\n";
}
which works as expected but seems overkill. It seems that a simple preprocessor macro of the form
#define k(z) f(z,y)
would also work. Is there a good way of achieving this?
Not sure if this is what you are attempting to do but here is a working (c++14) example:
#include <iostream>
struct mystruct {
static auto f (int x, int y) -> int {
std::cout << "f(" << x << "," << y << ")" << std::endl;
auto g = [=](auto z) -> decltype(mystruct::f(z, y)) {
return mystruct::f(z, y);
};
if (x < 1)
g("end");
else
g(x - 1);
}
static auto f (std::string x, int y) -> float {
std::cout << "f(\"" << x << "\"," << y << ")" << std::endl;
}
};
int main() {
mystruct::f(10, 1);
}
Output:
f(10,1)
f(9,1)
f(8,1)
f(7,1)
f(6,1)
f(5,1)
f(4,1)
f(3,1)
f(2,1)
f(1,1)
f(0,1)
f("end",1)
Am I missing something?
This produces the same answer, and I think is a little clearer:
#include <string>
#include <iostream>
struct mystruct
{
auto f( std::string x, int y) -> float {
return y+9.3;
}
auto f( int x, int y) -> int
{
switch(x)
{
case 0: {
auto g = [=](auto...args) { return f(args..., y); };
std::cout << g("this string") << "\n";
return 0;
} break;
case 1: {
return y;
} break;
default:
return 7;
}
}
};
int main () {
mystruct h;
std::cout << h.f(1,4) << "\n";
std::cout << h.f(0,2) << "\n";
}
Maybe in reality there are more switch cases, and g needs to be hoisted above the switch statement?

Very specific sub-class method call

I have this design:
class GenericData
{
};
class Data1 : public GenericData
{
};
class Data2 : public GenericData
{
};
class CompBase
{
public:
void process()
{
// inputs are check to make sure there number and order is correct
// Use them to automatically call the correct function
// What here ?
}
vector<GenericData> inputs;
};
class Comp1 : public CompBase
{
public:
void compute(Data1 input1, Data1 input2) { cout << "Comp1::compute(Data1 input1, Data1 input2)" << endl; }
void compute(Data2 input1, Data2 input2) { cout << "Comp1::compute(Data2 input1, Data2 input2)" << endl; }
void compute(Data1 input1, Data2 input2) { cout << "Comp1::compute(Data1 input1, Data2 input2)" << endl; }
};
class Comp2 : public CompBase
{
public:
void compute(Data1 input1) { cout << "Comp2::compute(Data1 input1)" << endl; }
void compute(Data2 input1) { cout << "Comp2::compute(Data2 input1)" << endl; }
};
With the following constraints:
The compute functions must be called from GenericComp but can't be all declared here because there would be two many (Data1,2 and Comp1,2 are just examples)
I must be able to have a collection of CompBase
The compute functions must not have to check their inputs (i.e. passing them the same structure is not possible)
The code must be generic enough to allow addition of other Data, Comp and compute easily
Here is an example of use:
int main() {
Data1 d1; Data2 d2;
Comp1 c1; Comp2 c2;
c1.inputs = { d1, d1 };
c1.process(); // "Comp1::compute(Data1 input1, Data1 input2)"
c1.inputs = { d2, d2 };
c1.process(); // "Comp1::compute(Data2 input1, Data2 input2)"
c1.inputs = { d1, d2 };
c1.process(); // "Comp1::compute(Data1 input1, Data2 input2)"
vector<GenericComp> comps = { c1, c2 };
for (comp : comps)
{
comp.process();
}
return 0;
}
I have a "working" example of this here.
I tried different approaches: CRTP, variadic template functions, currying and partial application and a lot of googling but I'm stuck here.
Is it possible with these constraints ? If so how could you do that ?
Thank you guys for the answers.
#Daniel Jour, your post really helped me and I had few modifications to make to fit my case.
Here is an updated example that will work for me.
#include <iostream>
#include <vector>
#include <map>
#include <functional>
#include <memory>
using namespace std;
class GenericData
{
public:
virtual ~GenericData() {};
};
class Data1 : public GenericData
{
public:
virtual ~Data1() {};
};
class Data2 : public GenericData
{
public:
virtual ~Data2() {};
};
class GenericComp
{
public:
virtual ~GenericComp() {};
vector<GenericData*> inputs;
};
class Comp1 : public GenericComp
{
public:
static bool compute(shared_ptr<Data1> const & input1, shared_ptr<Data1> const & input2) { cout << "Comp1::compute(Data1 input1, Data1 input2)" << (input2 ? "ok" : "null") << endl; return true; }
static bool compute(shared_ptr<Data2> const & input1, shared_ptr<Data2> const & input2) { cout << "Comp1::compute(Data2 input1, Data2 input2)" << endl; return true; }
static bool compute(shared_ptr<Data1> const & input1, shared_ptr<Data2> const & input2) { cout << "Comp1::compute(Data1 input1, Data2 input2)" << endl; return true; }
};
class Comp2 : public GenericComp
{
public:
static bool compute(shared_ptr<Data1> const & input1) { cout << "Comp2::compute(Data1 input1)" << endl; return true; }
static bool compute(shared_ptr<Data2> const & input1) { cout << "Comp2::compute(Data2 input1)" << endl; return true; }
};
// Arguments type to the function "interface"
using Arguments = std::vector<shared_ptr<GenericData>> const &;
// the interface
using Function = std::function<bool (Arguments)>;
// Base case of packing a function.
// If it's taking a vector and no more
// arguments, then there's nothing left to
// pack.
template<std::size_t N, typename Fn>
Function pack(Fn && fn)
{
return [fn = std::forward<decltype(fn)>(fn)] (Arguments arguments)
{
if (N != arguments.size())
{
throw std::string{"wrong number of arguments, expected "} +
std::to_string(N) +
std::string{" but got "} +
std::to_string(arguments.size());
}
return fn(arguments);
};
}
// pack a function to a function that takes
// it's arguments from a vector, one argument after
// the other.
template<std::size_t N, typename Arg, typename... Args, typename Fn>
Function pack(Fn && fn)
{
return pack<N+1, Args...>([fn = std::forward<decltype(fn)>(fn)] (Arguments arguments, Args const &... args)
{
try
{
return fn(arguments, arguments.at(N), args...);
}
catch (std::bad_cast const &)
{
throw std::string{"argument "} + std::to_string(N) + std::string{" has wrong type "};
}
});
}
// transform a function into one that takes its
// arguments from a vector
template<typename... Args, typename Fn>
Function pack_function(Fn && fn)
{
return pack<0, Args...>([fn = std::forward<decltype(fn)>(fn)] (Arguments arguments, Args const &... args) -> bool
{
return fn(args...);
});
}
int main() {
// Pack all the functions
std::map<std::string, Function> operations;
operations["Comp1_Data1_Data1"] = pack_function<shared_ptr<GenericData>, shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1, shared_ptr<GenericData> const & i2)
{
return Comp1::compute(dynamic_pointer_cast<Data1>(i1), dynamic_pointer_cast<Data1>(i2));
});
operations["Comp1_Data2_Data2"] = pack_function<shared_ptr<GenericData>, shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1, shared_ptr<GenericData> const & i2)
{
return Comp1::compute(dynamic_pointer_cast<Data2>(i1), dynamic_pointer_cast<Data2>(i2));
});
operations["Comp1_Data1_Data2"] = pack_function<shared_ptr<GenericData>, shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1, shared_ptr<GenericData> const & i2)
{
return Comp1::compute(dynamic_pointer_cast<Data1>(i1), dynamic_pointer_cast<Data2>(i2));
});
operations["Comp2_Data1"] = pack_function<shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1)
{
return Comp2::compute(dynamic_pointer_cast<Data1>(i1));
});
operations["Comp2_Data2"] = pack_function<shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1)
{
return Comp2::compute(dynamic_pointer_cast<Data2>(i1));
});
// Create the possible inputs
vector<shared_ptr<GenericData>> data1_data1 { shared_ptr<Data1>(), shared_ptr<Data1>() };
vector<shared_ptr<GenericData>> data2_data2 { shared_ptr<Data2>(), shared_ptr<Data2>() };
vector<shared_ptr<GenericData>> data1_data2 { shared_ptr<Data1>(), shared_ptr<Data2>() };
vector<shared_ptr<GenericData>> data1 { shared_ptr<Data1>() };
vector<shared_ptr<GenericData>> data2 { shared_ptr<Data2>() };
// The calls !
operations["Comp1_Data1_Data1"](data1_data1);
operations["Comp1_Data2_Data2"](data2_data2);
operations["Comp1_Data1_Data2"](data1_data2);
operations["Comp2_Data1"](data1);
operations["Comp2_Data2"](data2);
// Wrong arguments
try
{
operations["Comp1_Data1_Data1"](data1);
}
catch (std::string const & e)
{
cout << e << endl;
}
try
{
operations["Comp2_Data1"](data1_data1);
}
catch (std::string const & e)
{
cout << e << endl;
}
return 0;
}

Lambda functions as class members

Is it possible to accept two different types of lambda function as class members without knowing their template arguments ahead of time?
struct two_functors {
std::function<???> a;
std::function<???> b;
...
};
Such that something like this would be possible:
void main(){
vector<two_functors> many_functors;
int a = 2;
int b = 3;
double c = 4.7;
double d = 8.4;
two_functors add_and_subtract;
add_and_subtract.a = [a, b](int x, int y){cout << x + y << endl;};
add_and_subtract.b = [c, d](double x, double y){cout << x - y << endl;};
two_functors multiply_and_divide;
multiply_and_divide.a = [c, d](double x, double y){cout << x * y << endl;};
multiply_and_divide.b = [a, b](int x, int y){cout << x / y << endl;};
many_functors.push_back(add_and_subtract);
many_functors.push_back(multiply_and_divide);
for (auto functors : many_functors){
functors.a();
functors.b();
}
}
If you just want to construct two_functors at various times, but execute them later in sequence all at once, you could just use the captured data.
struct two_functors
{
function<void ()> a;
function<void ()> b;
};
int main()
{
vector<two_functors> many_functors;
int a = 2;
int b = 3;
double c = 4.7;
double d = 8.4;
two_functors add_and_subtract {
[a, b](){cout << a + b << endl;},
[c, d](){cout << c - d << endl;}
};
two_functors multiply_and_divide {
[c, d](){cout << c * d << endl;},
[a, b](){cout << a / b << endl;}
};
many_functors.push_back(add_and_subtract);
many_functors.push_back(multiply_and_divide);
for (auto functors : many_functors){
functors.a();
functors.b();
}
}
That's essentially a tuple. You can see how the interface is implemented for that.
template< class F0, class F1 >
struct two_functors {
F0 func0;
F1 func1;
};
template< class F0, class F1 >
two_functors<F0, F1> make_two_functor( F0&& f0, F1&& f1 )
{
// Added [std::forward][2]
return two_functors<F0,F1>( std::forward<F0>(f0), std::forward<F1>(f1) );
}
Not an attempt to answer (I just need the formatting feat), just a variation of Steven's proposal
template<typename A, typename B>
two_functors<A,B> make_two_functors(A&& a, B&& b) {
return two_functors<A,B> {a, b};
}
Does that have any downside compared to using std::forward<T>?
Btw - I somehow wish the need for such "makers" would have vanished with C++11.
An alternative to Steven's answer would be to use an intermediate "umbrella" class.
EDIT: Just compiled an example on g++ (GCC) 4.5.3
#include <functional>
#include <iostream>
using namespace std;
class myfunction
{
};
template <typename T>
class specificFunction : public myfunction
{
public:
function<T> f;
specificFunction(function<T> pf)
{
f = pf;
}
};
struct two_functors {
myfunction* a;
myfunction* b;
};
int main()
{
myfunction* f = new specificFunction<void(int,int)> ([](int a, int b) { cout << a << " - " << b << endl; });
myfunction* f2 = new specificFunction<void(double,int)> ([](double a, int b) { cout << a << " - " << b << endl; });
two_functors tf;
tf.a = f;
tf.b = f2;
((specificFunction<void(int,int)>*)(tf.a))->f(4,5);
((specificFunction<void(double,int)>*)(tf.b))->f(4.02,5);
}

Is there a way to generalize functions that only differ by an operation?

For example, suppose we have two functions:
void sum(int x, int y)
{
return x+y;
}
void minus(int x, int y)
{
return x-y;
}
Is there a way to make a single function that does a sum or minus (or various other things) depending on which you want to use (perhaps by a keyword of some sort) without having to write separate functions explicitly?
Some one kind of beat me to this with the comments below the question, but here ya go!
#include <functional>
#include <iostream>
#include <unordered_map>
std::unordered_map<std::string, std::function<int(int,int)>> operations =
{
{ "plus", std::plus<int>() },
{ "minus", std::minus<int>() }
// etc etc
};
int main(int argc, char** argv)
{
std::cout << operations["plus"](1, 2) << std::endl;
std::cout << operations["minus"](2, 1) << std::endl;
}
I assume the function is actually a bit more beefy than the one you posted (which don't compile returning a value from a function returning void). You could use function objects to customize the behavior, e.g.:
#include <functional>
#include <iostream>
using namespace std::placeholders;
template <typename Op>
int operation(int a0, int a1, Op op = Op())
{
return op(a0, a1);
}
int my_f0(int a0, int a2)
{
return 2 * a0 + 3 * a2;
}
int my_f2(int a0, int a2, int f0, int f1)
{
return f0 * a0 + f1 * a2;
}
int main()
{
std::cout << operation<std::plus<int> >(2, 3) << "\n";
std::cout << operation<std::minus<int> >(2, 3) << "\n";
std::cout << operation(2, 3, std::multiplies<int>()) << "\n";
std::cout << operation(2, 3, my_f0) << "\n";
std::cout << operation(2, 3, std::bind(&my_f2, _1, _2, 2, 3)) << "\n";
}
The customized function is operation(). The other code is just to show how it gets customized. The standard library algorithms use this approach all over the place.
Is it that you don't want to write separate functions, or that you want to call one thing from the call site? If you don't mind writing a little bit more, you can use operator objects:
class Add {
public:
int operator(int a, int b) {
return a+b:
}
};
class Mul {
public:
int operator(int a, int b) {
return a*b:
}
};
template <class Op>
int doMyStuff(Op op, int a, int b) {
return op(a,b);
}
// and you can call it like this:
doMyStuff(Add(),2,4);
This pattern is particularly useful when you implement certain transformations that do not rely on particular operator, but just on certain property of the operator. For example, you could implement an array-summator which either sums all elements of an array, or computes a product of all elements in array: the loop remains the same, it's just the operator that changes.
template <class Op>
int summator(Op op, int* arr, int size) {
int v = arr[0];
for (int i=1; i<size; ++i) {
v = op(v,arr[i]);
}
return v;
}
...
summator(Add(),myarray,10); //sum all elements
summator(Mul(),myarray,10); //product of all elements
If you don't believe macros are evil from hell, you could do this:
#define DEFINE_OPERATION(maName, maOp) \
inline int maName (int a, int b) { return a maOp b; }
DEFINE_OPERATION(add, +)
DEFINE_OPERATION(sub, -)
#undef DEFINE_OPERATION
Or even:
#include <boost/preprocessor.hpp>
#define OPERATIONS ((add, +))((sub, -))
#define DEFINE_OPERATION(maR, maData, maElem) \
inline int BOOST_PP_TUPLE_ELEM(2, 0, maElem) (int a, int b) { return a BOOST_PP_TUPLE_ELEM(2, 1, maEleme) b; }
BOOST_PP_SEQ_FOR_EACH(OPERATIONS, unused_, DEFINE_OPERATION)
#undef DEFINE_OPERATION
#include <iostream>
#include <functional>
using namespace std;
template<template<class> class OP, class T>
T do_op(T a, T b) {
return OP<T>()(a,b);
}
int main () {
cout << do_op<plus> (3,2) << endl;
cout << do_op<minus> (3,2) << endl;
cout << do_op<multiplies> (3,2) << endl;
cout << do_op<divides> (3,2) << endl;
}