I'd like to write a sort-of wrapper function for my class... And i really dont know how to do that!
See, i want a, say, run(), function, to accept a function as an argument, thats the easy part.
The usage would be something like
void f() { }
void run(int (*func)) {
//whatever code
func();
//whatever code
}
run(f);
That should just run the f() function, right?
But what if f() had required arguments? Say it was declared as f(int i, int j), i would go along rewriting the run() function to separately accept those ints, and pass them to the f() function.
But I'd like to be able to pass Any function to run(), no matter how many arguments, or what type they are. Meaning, in the end, i'd like to get usage similar to what i would expect the hypothetical
void f() {int i, int j}
void v() {char* a, int size, int position}
void run(int (*func)) {
//whatever code
func();
//whatever code
}
run(f(1, 2));
run(v(array, 1, 2));
to do. I know it looks dumb, but i think i'm getting my point across.
How would i do that?
Please remember that this is arduino-c++, so it might lack some stuff, but i do believe there are libraries that could make up for that...
If you have access to std::function then you can just use that:
void run(std::function<void()> fn) {
// Use fn() to call the proxied function:
fn();
}
You can invoke this function with a lambda:
run([]() { f(1, 2); });
Lambdas can even capture values from their enclosing scope:
int a = 1;
int b = 2;
run([a, b]() { f(a, b); });
If you don't have std::function but you can use lambdas, you could make run a template function:
template <typename T>
void run(T const & fn) {
fn();
}
Related
I have a fairly big project that, regarding this question,
I can summarize with
this structure:
void do_something()
{
//...
}
template<typename F> void use_funct(F funct)
{
// ...
funct();
}
int main()
{
// ...
use_funct(do_something);
}
All is working ok until someone (me) decides to reformat a little
minimizing some functions, rewriting
as this minimum reproducible example:
void do_something(const int a, const int b)
{
//...
}
void do_something()
{
//...
do_something(1,2);
}
template<typename F> void use_funct(F funct)
{
// ...
funct();
}
int main()
{
// ...
use_funct(do_something);
}
And now the code doesn't compile with
error: no matching function for call
where use_funct is instantiated.
Since the error message was not so clear to me
and the changes were a lot I wasted a considerable
amount of time to understand that the compiler
couldn't deduce the template parameter
because do_something could now refer to
any of the overloaded functions.
I removed the ambiguity changing the function name,
but I wonder if there's the possibility to avoid
this error in the future not relying on template
argument deduction.
How could I specify in this case the template argument for do_something(), possibly without referring to a function pointer?
I haven't the slightest idea to express explicitly:
use_funct<-the-one-with-no-arguments->(do_something);
You can wrap the function in a lambda, or pass a function pointer after casting it to the type of the overload you want to call or explicitly specify the template parameter:
use_funct([](){ do_something (); });
use_funct(static_cast<void(*)()>(do_something));
use_funct<void()>(do_something);
Wrapping it in a lambda has the advantage, that it is possible to defer overload resolution to use_func. For example:
void do_something(int) {}
void do_something(double) {}
template<typename F> void use_funct(F funct) {
funct(1); // calls do_something(int)
funct(1.0); // calls do_something(double)
}
int main() {
use_funct([](auto x){ do_something (x); });
}
[...] possibly without referring to a function pointer?
I am not sure what you mean or why you want to avoid that. void() is the type of the function, not a function pointer. If you care about spelling out the type, you can use an alias:
using func_type = void();
use_funct<func_type>(do_something);
What is considered to be best or good practice when declaring type aliases for function types in C++ (I know this part of the question is probably subjective)? Either
using FuncType = void(int, int);
or
using FuncType = std::function<void(int, int)>;
Are there benefits of one over the other?
How should I use these types as function arguments (when passing as functor, lambda, member or global function), for example
void foo(FuncType&& func) { ... }
void foo(FuncType func) { ... }
void foo(std::function<FuncType> func) { ... }
EDIT
I know that not all of my examples above are applicable with both #1 and #2 but that is not the point. I want to know which (and why) option is better and how should I pass this type when using it as a function argument.
Specific use case
As it appears to be too broad (which I absolutely understand) I'm going to give more detail about my specific case.
I have a class that holds a vector of functions that I want to call (most likely parallel, but I don't think this matters). In this class I can add functions to the vector at runtime.
For example:
class
Container
{
public:
using FuncType = std::function<void(const SomeComplexDataType&, int, double)>;
inline void addFunction(FuncType func)
{
_funcs.push_back(func);
}
inline void call(const SomeComplexDataType& a, int b, double c)
{
for (auto& func : _funcs)
func(a, b, c);
}
private:
std::vector<FuncType> _funcs{};
};
struct HeavyFunctor
{
// contains some heavy objects
void operator()(const SomeComplexDataType& a, int b, double c)
{
/* Some heavy workload */
}
};
int main()
{
Container c;
c.addFunction([](const SomeComplexDataType& a, int b, double c) { /* do something lightweight */ });
c.addFunction(HeavyFunctor);
c.call(x, y, z);
return 0;
}
How should I define FuncType and the parameter for addFunction and how can I store them in the vector (in a best case scenario, without copying the callables)?
I'd personnaly use:
typedef std::function<void(int,int)> FuncType;
and
void foo(const FuncType &func) { ... }
edit:
Not the best for performance considering comment on this post as it requires virtual dispatch.
My C++ is rusty. I'd like MyClass to know nothing about Foo and have a callback to run a function in foo. I don't know how to define callback_pair or how to call SetCallback
class MyClass{
tuple<cb, ptr> callback_pair
int run() {
auto that=callback_pair<1>();
auto cb = callback_pair<0>();
int a=1, b=2, c=3;
auto result = cb(that, a, b, c); //this calls foo.the_function
return result;
}
void SetCallback(tuple<cb, ptr> cb) { callback_pair=cb; )
};
class Foo {
int d;
int the_func(int a, b, c) {
return a+b+c+d
}
}
//myclass.SetCallback(what_do_I_write_here)
Well, MyClass must know something about Foo, namely the signature of whatever method you plan on using as a callback; otherwise, how would it know what to pass in as parameters, or what type to expect to get as output? If the callback signature is known and fixed, for instance int(int,int,int) as you have above, you could use a construction like this:
class MyClass {
std::function<int(int,int,int)> callback;
public:
int run() {
return callback(1,2,3); // or whatever
}
template <typename Class>
void SetCallback (Class& o, int (Class::*m) (int,int,int)) {
callback = [&o,m] (int a, int b, int c) { return (o.*m)(a,b,c); };
}
template <typename Class>
void SetCallback (Class const& o, int (Class::*m) (int,int,int) const) {
callback = [&o,m] (int a, int b, int c) { return (o.*m)(a,b,c); };
}
};
The above implementation of MyClass works as follows: callback is a function object, initially undefined, which takes three ints and returns an int. SetCallback takes two parameters: An object o on which the callback should be performed and a method m on that object which conforms to the signature of callback. It doesn't care what the type of o is; thanks to type-erasure, MyClass never needs to know what it's actually calling.
Take special notice of the two versions of SetCallback -- one each for const and non-const objects. In reality, you should be writing overloads for volatile and const volatile as well, but those are comparatively much rarer than const. In the future, once exception specifications and transactions become part of the type system, we will also have to care about noexcept and synchronization, and the resulting combinatoric explosion of types will be difficult to deal with effectively without some very clever language support. But this example shows you how that sort of code would be written, and it's probably good enough for your purposes.
The implementation looks ugly, but it actually provides a very clean interface; given Foo as you've written above, you would use MyClass's callback functionality like this:
MyClass test;
Foo foo;
foo.d = 4;
test.SetCallback (foo, &Foo::the_func);
int result = test.run(); // result = 10
The above code will work with any type that has a method with the signature int(int,int,int). Note that you must call SetCallback before you call run, or else you'll get a std::bad_function_call exception because the callback hasn't been defined yet.
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.
I have an overload function, with the following signatures:
void Foo(const std::function<void(int )> &func);
void Foo(const std::function<void(int, int)> &func);
And when I want to use Foo() with lambdas, I'll have to do something like this:
Foo((std::function<void(int )>) [] (int i ) { /* do something */ });
Foo((std::function<void(int, int)>) [] (int i, int j) { /* do something */ });
Both of which are not so user-friendly. It'd be a lot easier to use the function without having to add the casting "(std::function<...>)" before the lambdas - like this:
Foo([] (int i ) { /* do something */ }); // executes the 1st Foo()
Foo([] (int i, int j) { /* do something */ }); // executes the 2nd Foo()
So, I need another overload, that accept lambda as its argument, and which automatically casts the lambda to one of the above signatures. How can this be done? Or, is it possible in the first place?
template <typename Function> void Foo(Function function) {
// insert code here: should be something like
// - check the signature of the 'function'; and
// - call 'Foo()' corresponding to the signature
}
Please help.
PS. I'm using VS2010.
If your lambda does not capture any variables—that is, it begins with []—then it is convertible to a function pointer, and you can declare Foo like so:
void Foo(void(*func)(int));
void Foo(void(*func)(int, int));
If you want to keep the std::function versions, you can have these versions forward to that one. If you don’t want to implement them separately, I think a variadic template would do nicely:
template<class... Args>
void Foo(void(*func)(Args...)) {
return std::function<void(Args...)>(func);
}
If your lambdas capture variables, then they’re not convertible to function pointers, and you’ll need to wrap them in std::function yourself.
Lambda's convert to std::function<> implicitly, there's no explicit conversion needed.
std::function<void(int, int)> func = [](int a, int b){ printf("Hello Lambda world!"); };
func(1, 2);
Ah, you're trying to get a const reference to it. Why though? You should be better off with a right-hand reference (as it's a temporary) or a copy. In both of those cases it should implicitly convert as well...