passing functions - c++

Ok, it's been a while since I wrote in C++.
and I've never done anything quiet this high level.
So basically I need to create a class.
The constructor for the class needs to take a reference (or pointer) to a method form another class, or to a function.
Basically I have a class that needs to on occasion read a value from a fltk valuator (version 1.1.x), and then change some stuff about itself.
Each object will have it's own valuator associated with it.
(they also have a link to another object of the same parent, which after updating them selves from the valuator will tell to update, and so on)
So how do i pass functions around, in constructors?

Here is an example where a method of Foo is passed to the Bar constructor and later invoked on a given Bar object:
struct Foo
{
int z;
int add(int x, int y)
{
return x + y + z;
}
int mul(int x, int y)
{
return x * y * z;
}
};
typedef int (Foo::*foo_method)(int, int);
struct Bar
{
foo_method m;
Bar(foo_method m) : m(m) {}
int call_on(Foo* foo)
{
return (foo->*m)(4, 2);
}
};
int main()
{
Bar bar(&Foo::add);
Foo foo = { 123 };
bar.call_on(&foo);
}
If, on the other hand, you already know the Foo object at Bar construction time, then Bar does not really care which class the method belongs to. All it needs is a functor to call later, and the Foo object can simply be bound by the client.
#include <functional>
struct Bar
{
std::function<int (int, int)> f;
Bar(std::function<int (int, int)> f) : f(f) {}
int call()
{
return f(4, 2);
}
};
using namespace std::placeholders;
int main()
{
Foo foo = { 123 };
Bar bar(std::bind(&Foo::add, &foo, _1, _2));
bar.call();
}
If you don't have a C++0x compiler, replace std::bind with std::tr1::bind or boost::bind.

Your constructor might look something like this:
// convenient typedef. This is for a pointer to a function in Foo
// The function returns void and takes no parameters.
typedef void (Foo::*FooPtr)();
class Bar {
public:
Bar (FooPtr foo_ptr);
};
Check out some web references for more details on the syntax for pointer-to-members. It's a lot easier if you get familiar with it first.
As an additional note, check out the functions mem_fun and mem_fun_ref. These may do what you need.

The easiest way to capture this is with boost::function. It can store function pointers, but also the result of binding a member function to an object.
For instance,
class Foo {
Foo(boost::function<int(void)>);
};
will allow you to accept any source of integers.

Related

Is it possible in C++14 to capture specific member variables by reference [duplicate]

I have a class that has function pointer to kernel function, that can change from outside.
class Bar
{
public:
int i;
}
class Foo
{
public:
std::function<double()> kernel;
Bar bar;
};
int main()
{
Foo f;
f.kernel = []() -> double { return i * i; }; //this is not working obviously
}
How can I achieve behaviour that is "presented", eg. read class variables inside lambda. I can bypass it by passing f inside and write f.bar.i, but that is not very nice solution.
In C++14 you can write it as,
f.kernel = [&i = f.bar.i]() -> double { return i * i; };
If you don't have C++14, you can alternatively create another variable,
int &i = f.bar.i;
f.kernel = [&i]() -> double { return i*i; };
Though there's nothing wrong with passing f and writing f.bar.i.
It seems that you cannot do so.
There is no construct to create a member function lambda.
But you probably can follow #KerrekSB's suggestion and in addition to that dispatch the call to still get the member function:
class Foo
{
public:
double kernel()
{
_kernel(*this);
}
std::function<double(Foo &)> _kernel;
};
Foo f;
f._kernel = [](Foo &f) -> double { return f.i * f.i; };
f.kernel()
Note that you cannot name both fields kernel.
The lambda function does not know about i or Bar. How could it know? You need to pass a Reference. If you define the function body differently so you can pass i as parameter and you call it within the class you should get what you want.

Store a reference of an object's method received from a function

I was able to pass an object's non static method Dummy to another object's function. The problem comes when I try to store the reference of that method into the object of the function, I don't know how to do it.
#include <iostream>
#include <functional>
class Dummy{
public:
void runDummyArgs(int z){std::cout<<"TEST: "<<z<<std::endl;};
};
class Test{
public:
template<typename X , typename T>
void runTest(X* obj, T(X::* func), int z) { (obj->*func)(z); };
/* It works, but I would like to store (obj->*func) in this class as a reference to reuse it when it is needed. */
};
int main()
{
Dummy *a = new Dummy();
Test *b = new Test();
b->runTest(a, &Dummy::runDummyArgs, 99);
return 0;
}
I would write something that looks like:
#include <iostream>
#include <functional>
class Dummy{
public:
void runDummyArgs(int z){std::cout<<"TEST: "<<z<<std::endl;};
};
class Test{
std::function<void(int)> mFunc; // added member to hold function
public:
// added constructor to accept function
Test(std::function<void(int)> func): mFunc(func)
{
}
// no longer needs any templating. It's all handled by std::function
// most of the parameters bound by std::function
void runTest(int z)
{
mFunc(z);
};
};
int main()
{
Dummy a; // no need for dynamic allocation. Only use new when forced
// and that's almost never thanks to containers and smart pointers
// This line gets a bit weird. I'll explain it below
Test b([&a](int z){a.runDummyArgs(z);});
b.runTest(99); // just needs the end argument of the function
return 0;
}
OK. That's not so bad. Except for
Test b([&a](int z){a.runDummyArgs(z);});
Test requires a std::function that takes an int and returns nothing. [&a](int z){a.runDummyArgs(z);} is a lambda expression (More documentation that gets into the niggly bits and details) that defines a callable object that takes an int and returns nothing. The resulting instance will be called b. Breaking the lambda down further:
[&a]
Captures variable a by reference. This allows modifying a inside the lambda. Sometimes you want the lambda to carry around its own copy of a, for example if a is a temporary variable that won't be around when the function is called later. To stave off the common future questions about dangling references and const Dummy compiler errors, I'll add a simple example of capture by mutable value to the end of this answer.
(int z)
lambda's parameters
{a.runDummyArgs(z);}
function body that invokes runDummyArgs on a.
More complicated capture by mutable value example:
#include <iostream>
#include <functional>
class Dummy{
int val = 0; // provide some visible state for instances
public:
void runDummyArgs(int z)
{
std::cout<<"TEST: "<<z + val << std::endl;
// ^ added to show changing state
val++; // change state
}
};
class Test{
std::function<void(int)> mFunc;
public:
Test(std::function<void(int)> func): mFunc(func)
{
}
void runTest(int z)
{
mFunc(z);
};
};
std::function<void(int)> builder()
{
Dummy a;
return [a](int z)mutable{a.runDummyArgs(z);};
// ^ the copy of a can be modified.
} // a goes out of scope here, but its copy in the lambda lives on
int main()
{
Test b(builder());
b.runTest(99); // print 99
b.runTest(99); // print 100
Test c(builder());
c.runTest(99); // print 99 because we have a copy of a different dummy instance
c.runTest(99); // print 100
return 0;
}

C++ lambda - capture member variable

I have a class that has function pointer to kernel function, that can change from outside.
class Bar
{
public:
int i;
}
class Foo
{
public:
std::function<double()> kernel;
Bar bar;
};
int main()
{
Foo f;
f.kernel = []() -> double { return i * i; }; //this is not working obviously
}
How can I achieve behaviour that is "presented", eg. read class variables inside lambda. I can bypass it by passing f inside and write f.bar.i, but that is not very nice solution.
In C++14 you can write it as,
f.kernel = [&i = f.bar.i]() -> double { return i * i; };
If you don't have C++14, you can alternatively create another variable,
int &i = f.bar.i;
f.kernel = [&i]() -> double { return i*i; };
Though there's nothing wrong with passing f and writing f.bar.i.
It seems that you cannot do so.
There is no construct to create a member function lambda.
But you probably can follow #KerrekSB's suggestion and in addition to that dispatch the call to still get the member function:
class Foo
{
public:
double kernel()
{
_kernel(*this);
}
std::function<double(Foo &)> _kernel;
};
Foo f;
f._kernel = [](Foo &f) -> double { return f.i * f.i; };
f.kernel()
Note that you cannot name both fields kernel.
The lambda function does not know about i or Bar. How could it know? You need to pass a Reference. If you define the function body differently so you can pass i as parameter and you call it within the class you should get what you want.

How to curry a method on an object for passing it as a C-style callback?

Let's assume we have the following class A:
class A
{
public:
void sum(int x);
};
And we have a function f, which gets a C-style callback with one parameter of type int and calls it:
typedef void (*Callback)(int);
void f(Callback cb)
{
cb(5);
}
Is there any way in C++ to curry a method A::print on an object of type A and pass it to the function f? Something like this:
void main()
{
A a;
auto curry_a = ??; // something like curry_a = [&](int x) { a.sum(x) };
f(curry_a);
}
std::bind and lambda-function are not a solution, because they create objects of type std::function<> with overloaded operator(). It looks like currying in C++, but it cannot be used in my case. I need a real function pointer, i.e. generate code in real time.
You are out of luck, it can't be done in a satisfactory way: The only thing that is exactly a C-compatible function pointer is a function (or class-function but not instance function).
So, you'd have to create a function that fixes a parameter, like the this of a member function. The only way to set this parameter is through a global variable:
A *instance;
void (A::*a_fun)(int);
void applicator(int arg) { instance->*a_fun(arg); }
//...
int main() {
A a;
instance = &a;
a_fun = &A::sum;
f(applicator);
// ...
That is the only way to provide context to a plain function, through global variables.

Enforce function calls at compile time in C++

Is there a way in C++ to enforce function calls in compile time in such a way that this call will be allowed:
obj.reset().setParam1(10).setParam2(20);
but this one will fail to compile:
obj.reset().setParam1(10);
I want to avoid setting all parameters in one function since there are too many to be set; so I prefer to use something similar to named parameters idiom.
EDIT: Alternative syntax could be:
obj.reset(setParam1(10), setParam2(20));
or
obj.reset(setParam1(10).setParam2(20));
As the desired behaviour must be present at compile time, it needs to be implemented within the type system. To my understanding, this is impossible in C++ - the named parameters idiom relies on setter functions having the same return type (namely the type of the object which is called on), so calls to certain methods cannot be prevented.
I'll give you an example of doing that with the 2 parameters you provide, if you need more, it needs more work. If the requirement hierarchy between parameters get too complex, you may find it hard to structure your classes but here it goes:
class Obj {
Obj2 setParam2(int v);
}
class Obj2: public Obj {
Obj2 setParam1(int v);
}
int main() {
Obj obj;
obj.setParam2(10); // possible
obj.setParam2(10).setParam1(20); // possible
obj.setParam1(20); // not possible
obj.setParam1(20).setParam2(10); // unfortunately not possible
// Edit: one more limitation- consecutive calls are not possible,
// you must chain
obj.setParam2(20);
obj.setParam1(10); // problem
}
The best thing I could do to provide both named parameters and enforce all of them being initialized is this.
template<typename T>
struct Setter
{
Setter(const T &param) : ref(param) {}
const T &ref;
};
typedef Setter<int> Param1;
typedef Setter<std::string> Param2;
struct CObj
{
void reset(const Param1 &A, const Param2 &B) {
setParam1(A.ref); setParam2(B.ref); }
void setParam1(int i) { param1 = i; }
void setParam2(const std::string &i) { param2 = i; }
int param1;
std::string param2;
};
int main()
{
CObj o;
o.reset(Param1(10), Param2("hehe"));
}