void foo(int arg);
int foo2() {throw std::out_of_range("error!"); return 5;}
//Now I do this like that:
try { foo(foo2()); }
catch(std::out_of_range) {}
And what I want to do, is to catch the exception inside the foo function. However I have no idea how can I put try block in the arguments list?
you cant, because the exception isnt thrown before foo() was executed.
You can't. You either need to pull the call to foo2 out of the call to foo, and handle the exception in the calling routine, as such --
int param;
try {
param = foo2();
} catch(std::out_of_range) {}
foo(param);
or pass foo2 as a function to foo, and evaluate it inside foo, like this --
void foo(int (*arg_func)()) {
int arg;
try {
arg = arg_func();
} catch(std::out_of_range) {
std::cout << "out of range ";
}
}
the call then looks like this --
foo(foo2);
Of course, now you always have to pass a function to foo, no literals or expressions.
Most of time, I prefer #iagreen's solution. But in his/her solution, there is a dependence issue:
should foo know foo2's signature?
Of course we can get some conclusions in your original call foo(foo2())
the return value of foo2 should be convertible to int
foo does not need to know the amount of foo2's arguments nor their types, even what's the function invoked before foo
So I think a implementation by Variadic Template is more suitable in most cases.
template < typename F, typename... Args >
void foo( F f, Args&&... args ) {
int ret = f( std::forward<Args>(args)... );
std::cout << "ret = " << ret << std::endl;
}
Related
I'm trying to figure out how to get the address of a lambda function within itself. Here is a sample code:
[]() {
std::cout << "Address of this lambda function is => " << ????
}();
I know that I can capture the lambda in a variable and print the address, but I want to do it in place when this anonymous function is executing.
Is there a simpler way to do so?
There is no way to directly get the address of a lambda object within a lambda prior to c++23.
Now, as it happens this is quite often useful. The most common use is in order to recurse.
The y_combinator comes from languages where you could not talk about yourself until you where defined. It can be implemented pretty easily in c++:
template<class F>
struct y_combinator {
F f;
template<class...Args>
decltype(auto) operator()(Args&&...args) const {
return f( f, std::forward<Args>(args)... );
}
template<class...Args>
decltype(auto) operator()(Args&&...args) {
return f( f, std::forward<Args>(args)... );
}
};
template<class F>
y_combinator(F)->y_combinator<F>;
now you can do this:
y_combinator{ [](auto& self)-> void {
std::cout<<"Address of this lambda function is => "<< &self;
} }();
There are a few useful variations. One variation I find particularly useful is:
template<class F>
struct y_combinator {
F f;
template<class...Args>
decltype(auto) operator()(Args&&...args) const {
return f( *this, std::forward<Args>(args)... );
}
template<class...Args>
decltype(auto) operator()(Args&&...args) {
return f( *this, std::forward<Args>(args)... );
}
};
where the self passed can be called without passing in self as the first argument.
The second matches the real y combinator (aka the fixed point combinator) I believe. Which you want depends on what you mean by 'address of lambda'.
There is also this pithy one:
template<class R, class...Args>
auto Y = [] (auto f) {
auto action = [=] (auto action) -> std::function<R(Args...)> {
return [=] (Args&&... args)->R {
return f( action(action), std::forward<Args>(args)... );
};
};
return action(action);
};
which returns a std function.
In c++23 accessing this within a lambda gets easier:
auto fib = [](this auto& self, int n) {
if (n < 2) return n;
return self(n-1) + self(n-2);
};
you can tag the first argument as this, and it becomes itself. It even works with the overload set trick, where self is the most-deduced type.
It is not directly possible.
However, lambda captures are classes and the address of an object coincides with the address of its first member. Hence, if you capture one object by value as the first capture, the address of the first capture corresponds to the address of the lambda object:
int main() {
int i = 0;
auto f = [i]() { printf("%p\n", &i); };
f();
printf("%p\n", &f);
}
Outputs:
0x7ffe8b80d820
0x7ffe8b80d820
Alternatively, you can create a decorator design pattern lambda that passes the reference to the lambda capture into its call operator:
template<class F>
auto decorate(F f) {
return [f](auto&&... args) mutable {
f(f, std::forward<decltype(args)>(args)...);
};
}
int main() {
auto f = decorate([](auto& that) { printf("%p\n", &that); });
f();
}
One way to solve this, would be to replace the lambda with a hand written functor class. It's also what the lambda essentially is under the hood.
Then you can get the address through this, even without ever assigning the functor to a variable:
#include <iostream>
class Functor
{
public:
void operator()() {
std::cout << "Address of this functor is => " << this;
}
};
int main()
{
Functor()();
return 0;
}
Output:
Address of this functor is => 0x7ffd4cd3a4df
This has the advantage that this is 100% portable, and extremely easy to reason about and understand.
Capture the lambda:
std::function<void ()> fn = [&fn]() {
std::cout << "My lambda is " << &fn << std::endl;
}
It is possible but highly depends on the platform and compiler optimization.
On most of the architectures I know, there is register called instruction pointer. The point of this solution is to extract it when we are inside the function.
On amd64 Following code should give you addresses close to the function one.
#include <iostream>
void* foo() {
void* n;
asm volatile("lea 0(%%rip), %%rax"
: "=a" (n));
return n;
}
auto boo = [](){
void* n;
asm volatile("lea 0(%%rip), %%rax"
: "=a" (n));
return n;
};
int main() {
std::cout<<"foo"<<'\n'<<((void*)&foo)<<'\n'<<foo()<<std::endl;
std::cout<<"boo"<<'\n'<<((void*)&boo)<<'\n'<<boo()<<std::endl;
}
But for example on gcc https://godbolt.org/z/dQXmHm with -O3 optimization level function might be inlined.
So I am creating a type of event handler and I am in the process of writing an "Event Listener Wrapper", if you will.
The basic idea is this:
When you want to subscribe to an event, you create a function that should be called when the event fires. <-- already have that done (kinda, I'll explain)
You put this listener function into a wrapper to pass the function onto the dispatcher.
The dispatcher gets an event, finds the wrapper for you listener, and calls the underlying function with the parameter values set by the event.
I already have something working so long as the listeners all only accept one argument of my EventBase class. Then I have to type cast that into the proper event that the listener is passed.
What I want instead is for my listener functions to have "any" type of arguments, and store the function in a way that lets me call it with any arguments I want depending on the event fired. Each listener function would only ever receive one type of event, or the event it's self. This would allow me to not have to type cast each event in every listener, but instead the correct event would be passed.
I found a bit of code for this wrapper that is almost perfect, with a few minor issues that I can't seem to fix. I'll explain below.
Code by #hmjd:
#include <iostream>
#include <string>
#include <functional>
#include <memory>
void myFunc1(int arg1, float arg2)
{
std::cout << arg1 << ", " << arg2 << '\n';
}
void myFunc2(const char *arg1)
{
std::cout << arg1 << '\n';
}
class DelayedCaller
{
public:
template <typename TFunction, typename... TArgs>
static std::unique_ptr<DelayedCaller> setup(TFunction&& a_func,
TArgs&&... a_args)
{
return std::unique_ptr<DelayedCaller>(new DelayedCaller(
std::bind(std::forward<TFunction>(a_func),
std::forward<TArgs>(a_args)...)));
}
void call() const { func_(); }
private:
using func_type = std::function<void()>;
DelayedCaller(func_type&& a_ft) : func_(std::forward<func_type>(a_ft)) {}
func_type func_;
};
int main()
{
auto caller1(DelayedCaller::setup(&myFunc1, 123, 45.6));
auto caller2(DelayedCaller::setup(&myFunc2, "A string"));
caller1->call();
caller2->call();
return 0;
}
The first thing I did here was I had to replace std::unique_ptr with std::shared_ptr. Not sure why really. This almost works. In my use case, I need to store a method function (meaning bind needs to be passed the containing method object?), and at the time of storing the function I don't know what the argument value will be, thats up for the event to decide. So my adjustment is as follows:
class DelayedCaller
{
public:
template <typename TFunction, typename TClass>
static std::shared_ptr<DelayedCaller> setup(TFunction&& a_func,
TClass && a_class)
{
auto func = std::bind(std::forward<TFunction>(a_func),
std::forward<TClass>(a_class),
std::placeholders::_1);
return std::shared_ptr<DelayedCaller>(new DelayedCaller(func));
}
template <typename T>
void call( T v ) const { func_(v); }
private:
using func_type = std::function<void( )>;
DelayedCaller(func_type&& a_ft) : func_(std::forward<func_type>(a_ft)) {}
func_type func_;
};
For the sake of testing, I removed the parameter pack and replaced it with a direct parameter to the class object holding the function. I also gave the bind a placeholder for 1 argument (ideally replaced by the void call() function later).
It's created like this:
eventManager->subscribe(EventDemo::descriptor, DelayedCaller::setup(
&AppBaseLogic::getValueBasic,
this
));
Problem is: on this line:
return std::shared_ptr<DelayedCaller>(new DelayedCaller(func));
I get "no matching function for call to 'DelayedCaller::DelayedCaller(std::_Bind(AppBaseLogic*, std::_Placeholder<1>)>&)'
return std::shared_ptr(new DelayedCaller(func));"
This only happens when using the placeholder::_1. if I replace that with a known value of the correct type, it works, with the exception that the function gets called without any useful data of course.
So, I guess I need a way to store the function with placeholders that I don't know the type of?
Forgive me if I am getting names of things wrong. I am very new to c++, I have only started learning it the past few days.
**Edit: **
Ok, so I am just updating why I need to store functions like this.
I have a map in my event dispatcher that looks like this:
std::map< const char*, std::vector<DelayedCaller> > _observers;
I want to be able to call the function inside the "Delayed Caller" something like this:
void Dispatcher::post( const EventBase& event ) const
{
// Side Note: I had to do this instead of map.find() and map.at() because
// passing a "const char*" was not evaluating as equal to event.type() even
// though event.type() is also a const char*. So instead I am checking it
// myself, which is fine because it gives me a little more control.
std::string type(event.type());
for( auto const &x : _observers ) {
std::string type2(x.first);
if ( type == type2 ) {
auto&& observers = x.second;
for( auto&& observer : observers ) {
// event may be any descendant of EventBase.
observer.slot->call(event);
}
break;
}
}
}
My listeners currently look like this:
void AppBaseLogic::getValue(const EventBase &e) {
const EventDemo& demoEvent = static_cast<const EventDemo&>( e );
std::cout << demoEvent.type();
}
I am trying to store each function so that the argument may look like this:
void AppBaseLogic::getValue(const EventAnyDescendant &e) {
std::cout << e.type();
}
Hopefully that helps. Thank you all for taking the time to help me with this.
Side note on lambdas: Someone suggested them, I have know idea what they are or how to use them, but I am going to do some reaserch on them so see if that would make more sense. I am worried about maintainability with them though from what I have seen.
It isn't quite clear what your DelayedCaller is doing. If you refactor the code and get rid of it, you will get just this:
auto c1 = []() {myFunc1(123, 45.6);}; // or use bind, the result is exactly the same
auto c2 = []() {myFunc2("A string");};
vector<function<void()>> v {c1, c2};
v[0]();
v[1](); // ok
Now if you try to introduce the placeholder modification in this version, it becomes clear why it didn't work in the first place:
auto cSome = [](???) {getValueBasic(???)};
What do you replace the ??? with?
getValueBasic accepts some specific type of argument, and it will leak out into the cSome signature. No matter how many template wrappers you wrap it in, it will leak out into the signature of every wrapper up to and including the outermost one. bind and std::placeholders are not a magic wand capable of making it unhappen.
In other words, if you don't know the type of your function, you cannot call it (kind of obvious, isn't it?)
One way to type-erase the signature and have all callables to conform to the same type is to typecheck and typecast them at run time (a.k.a. dynamic_cast). Another one is double dispatch. Both methods are different incarnations of the same general idea of visitor. Google "the visitor pattern" for more info.
May be this suits you. using c++11
#include <iostream>
#include <functional>
#include <vector>
namespace test
{
std::vector<std::function<void()>> listeners;
template<typename F, typename... Args>
void add_listener(F call, Args&& ...args )
{
std::cout << "callback_dispatcher>" << __PRETTY_FUNCTION__ << "enter <<< " << std::endl;
auto invoke_me = [=]()mutable{
call(std::move(args)...);
};
listeners.push_back(invoke_me);
}
void dispatch_all()
{
for(auto func: listeners)
{
func();
}
}
}
int main()
{
std::cout << "Main entered..." << std::endl;
test::add_listener(
[](int a)
{
std::cout << "void(int) lambda dispatched with a = " << a << std::endl;
},
5
);
test::add_listener(
[](int a, std::string str)
{
std::cout << "void(int, string) lambda dispatched with a = " << a << ", str = " << str << std::endl;
},
10, "Hello World!"
);
test::dispatch_all();
std::cout << "Main exited..." << std::endl;
}
Output:
Main entered...
callback_dispatcher>void test::add_listener(F, Args&& ...) [with F = main()::<lambda(int)>; Args = {int}]enter <<<
callback_dispatcher>void test::add_listener(F, Args&& ...) [with F = main()::<lambda(int, std::__cxx11::string)>; Args = {int, const char (&)[13]}]enter <<<
void(int) lambda dispatched with a = 5
void(int, string) lambda dispatched with a = 10, str = Hello World!
Main exited...
Refer SO_QUESTION for why mutable and std::move is used when expanding args in a lambda.
Take a look at std::bind and perhaps std::mem_fn
The c+=11 version is able to do all sorts of clever transformations on your argument list to generate a function-like object.
Lambdas provide even more flexibility, of course, and you can mix them, mostly.
I see 2 main problems in your modified (method and placeholder) version of DelayedCaller
(1) now call() receive a parameter (of type T) so func_() is called with one parameter; but func_() remain defined of type std::function<void()>, so can't receive the parameter [this point is the reason of your "no matching function" error]
(2) if you templatize call(), receiving a parameter of with type T, it's necessary to templatize also the type of func_ that become std::function<void(T)>; so you have to templatize the full class.
Taking in count (1) and (2), and maintaining std::unique_ptr, I've rewritten your DelayedCaller as dcM1 (M for "method" and 1 for "1 parameter")
template <typename T>
class dcM1
{
public:
template <typename TFunction, typename TClass>
static std::unique_ptr<dcM1> setup (TFunction && a_func,
TClass && a_class)
{
auto func = std::bind(std::forward<TFunction>(a_func),
std::forward<TClass>(a_class),
std::placeholders::_1);
return std::unique_ptr<dcM1>(new dcM1(func));
}
void call( T v ) const
{ func_(v); }
private:
using func_type = std::function<void(T)>;
dcM1(func_type && a_ft) : func_(std::forward<func_type>(a_ft))
{ }
func_type func_;
};
and can be used as follows
auto cm1f = dcM1<int>::setup(&foo::func, &f);
auto cm1b = dcM1<long>::setup(&bar::func, &b);
cm1f->call(0);
cm1b->call(1L);
The following is a full working example
#include <iostream>
#include <string>
#include <functional>
#include <memory>
void myFunc1 (int arg1, float arg2)
{ std::cout << arg1 << ", " << arg2 << '\n'; }
void myFunc2 (char const * arg1)
{ std::cout << arg1 << '\n'; }
class dcVoid
{
public:
template <typename TFunction, typename... TArgs>
static std::unique_ptr<dcVoid> setup (TFunction && a_func,
TArgs && ... a_args)
{
return std::unique_ptr<dcVoid>(new dcVoid(
std::bind(std::forward<TFunction>(a_func),
std::forward<TArgs>(a_args)...)));
}
void call() const
{ func_(); }
private:
using func_type = std::function<void()>;
dcVoid(func_type && a_ft) : func_(std::forward<func_type>(a_ft))
{ }
func_type func_;
};
template <typename T>
class dcM1
{
public:
template <typename TFunction, typename TClass>
static std::unique_ptr<dcM1> setup (TFunction && a_func,
TClass && a_class)
{
auto func = std::bind(std::forward<TFunction>(a_func),
std::forward<TClass>(a_class),
std::placeholders::_1);
return std::unique_ptr<dcM1>(new dcM1(func));
}
void call( T v ) const
{ func_(v); }
private:
using func_type = std::function<void(T)>;
dcM1(func_type && a_ft) : func_(std::forward<func_type>(a_ft))
{ }
func_type func_;
};
struct foo
{ void func (int i) { std::cout << "foo func: " << i << std::endl; } };
struct bar
{ void func (long l) { std::cout << "bar func: " << l << std::endl; } };
int main ()
{
auto cv1 = dcVoid::setup(&myFunc1, 123, 45.6);
auto cv2 = dcVoid::setup(&myFunc2, "A string");
foo f;
bar b;
auto cm1f = dcM1<int>::setup(&foo::func, &f);
auto cm1b = dcM1<long>::setup(&bar::func, &b);
cv1->call();
cv2->call();
cm1f->call(0);
cm1b->call(1L);
}
Ok, So I know this has been sitting for a while. I've been doing heavy research into different event patterns trying to find something closer to what I was after. After pouring through everything, and with the advice of those who have left comments here, I have decided to use a Signal/Slot pattern, possibly the most widely used event pattern for C++. The way have have approached it is to have all of my "logic classes" (whether for a gui or for computation) keep a reference to a third "signal event holder class", which I am calling an event broker for simplicity. This is just about as good as I can get it. Any event that you might want to have can be added to this class, and it can be accessed and called from any class with a reference to the event broker. I found a pretty nice signal class made by Simon Schneegans, but I am actively trying to find/learn how to make something better (threadsafe, maybe faster?). If anyone is interested/looking for help like I was, you can find my super basic test case here:
https://github.com/Moonlight63/QtTestProject
Thanks!
I'd like to create a class, than when instantiated, accepts a variable number of function references that don't have signatures known beforehand. Here's an example that almost does what I want:
// To show the function refs being used
void p(int arg) { cout << "int " << arg << endl; }
void p(string arg) { cout << "string " << arg << endl; }
void p(int arg1, int arg2) { cout<<"int/int "<<arg1<<arg2<<endl; }
void p(int arg1, string arg2) { cout<<"int/string "<<arg1<<arg2<<endl; }
class foo {
public:
// CTOR takes variadic function refs
template <typename... Args>
foo(Args... args) { p(args()...); }
// "args()..." requires supplied functions to take no parameters
// but makes no requirement on their return values.
};
// Using lambdas, but free functions, std::bind(), etc. work too
foo i([]{return 1;}); // prints "int 1"
foo s([]{return string("one");}); // prints "string one"
foo b([]{return 2;},
[]{return string("two");}); // prints "int/string 2two"
What I can't see how to fix this so that the functions supplied as arguments are not evaluated in the constructor. I'd like the call to p(args()...) to be done later, by another method in foo. This is why foo can't be created as simply as foo i(1): the argument function(s) need to be called later, and multiple times, not just once when the object is created (and they'd be more complex than just returning a constant).
The problem seems to come down to saving references to the constructor parameters to be called later, when the class doesn't know how many or what signature those parameters will have. Somehow the arguments need to be part of a class template and not just a constructor template, but how?
If the functions passed all had the same signature, then one could use a class template with a non-type parameters and supply the functions as template arguments:
template <int (&...Arg)()>
class bar {
public:
bar() { p(Arg()...); }
other() { p(Arg()...); } // Use in any method
};
int one() { return 1; }
int two() { return 2; }
bar<one> bi; // Prints "int 1"
bar<one, two> bii; // Prints "int/int 12"
But this requires all the arguments be functions that return int and also doesn't work with lambdas as they can't be template arguments.
You can use a lambda and a std::function to do that.
Note that a lambda can capture a parameters pack and (let me say) unpack it later.
It follows a minimal, working example:
#include<iostream>
#include<functional>
void p(int arg) { std::cout << "int " << arg << std::endl; }
void p(std::string arg) { std::cout << "string " << arg << std::endl; }
void p(int arg1, int arg2) { std::cout<<"int/int "<<arg1<<arg2<<std::endl; }
void p(int arg1, std::string arg2) { std::cout<<"int/string "<<arg1<<arg2<<std::endl; }
class foo {
public:
template <typename... Args>
foo(Args... args): func{[args...](){ p(args()...); }} {}
void operator()() { func(); }
private:
std::function<void()> func;
};
int main() {
// create your objects...
foo i([]{return 1;});
foo s([]{return std::string("one");});
foo b([]{return 2;}, []{return std::string("two");});
// ... and use them later
i();
s();
b();
}
I want to call all types of functions from a single table.
(Consider returns types are all void)
To illustrate what I am talking about, here is some code that obviously does not work.
#include <iostream>
#include <map>
#include <functional>
void foo(int x){std::cout<<x;}
void bar(){std::cout<<"bar";}
std::map<std::string, std::function<void()>> map =
{
{"foo", foo},
{"bar", bar}
};
int main()
{
map["foo"](2);
map["bar"]();
}
I am not opposed to a C style solution.
You could declare your pointer an old style C function pointer to
a variadic function like:
foo(...);
bar(...);
std::map<void(*)(...)> map =
{
{"foo", foo},
{"bar", bar}
};
but then foo and bar have to follow the variadic calling convention with va_args, va_start
etc and you may only pull C PODs from the list. Don't know if its worth the hassle. The calling method still somehow has to know which number of args to pass.
Looks a bit as if you may rethink your design.
If for example this is supposed to be a command table for a kind of CLI it might be better to pass an std::vector<std::string> to each potential command and make it figure out if the vector has the correct size() for its purpose.
If you totally forsake the type system, you can use boost::any as long as you get all the types exactly right everywhere. Right now only works with explicitly making everything a std::function but I'm sure there's a workaround for that too (update added an overload for free functions):
class Functions
{
public:
template <typename... T>
void add_function(const std::string& name, void (*f)(T...))
{
fs[name] = std::function<void(T...)>{f};
}
template <typename... T>
void add_function(const std::string& name, std::function<void(T...)> f)
{
fs[name] = f;
}
template <typename... T>
void call(const std::string& name, T... args)
{
auto it = fs.find(name);
if (it != fs.end()) {
auto f = boost::any_cast<std::function<void(T...)>>(&it->second);
if (f) {
(*f)(args...);
}
else {
std::cout << "invalid args for " << name << std::endl;
}
}
else {
std::cout << "not found: " << name << std::endl;
}
}
private:
std::map<std::string, boost::any> fs;
};
void baz() {
std::cout << "baz" << std::endl;
}
int main() {
std::function<void()> foo = []{ std::cout << "foo" << std::endl; };
std::function<void(int)> bar = [](int i){ std::cout << "bar(" << i << ")" << std::endl;
};
Functions f;
f.add_function("foo", foo );
f.add_function("bar", bar);
f.add_function("baz", baz);
f.call("foo");
f.call("bar", 42);
f.call("baz");
}
Functional, yes. Good idea? Note also that f.call("bar", 42u) will fail because you have to get every type exactly right.
I changed a bit your approach, and be aware it's just an example, I'm pretty sure it won't compile like this, but it will give you an idea of what I had in mind.
You can register your functions in an additional struct, and then call the appropriate one, forwarding the parameters.
struct Funcs
{
std::function<void(int)> _f1;
std::function<void()> _f2;
template<typename args...>
void call(std::string&& f_name, args...)
{
if(f_name == "foo")
_f1(std::forward(args)...)
if(f_name == "bar")
_f2(std::forward(args)...)
}
}
int main()
{
Funcs f;
f.call("foo", 2);
}
If you really want to store any function, and can always figure out how to call it correctly, you can expand on Oncaphillis' approach and just go ahead and cast the function pointers:
void foo(int);
float bar(double, struct baz);
std::map<void(*)()> map = {
{"foo", (void(*)())foo},
{"bar", (void(*)())bar}
};
Then you can cast them back when you use them:
//code to make sure that map["foo"] is of type `void(*)(int)`
(*(void(*)(int))map["foo"])(42);
//code to make sure that map["bar"] is of type `float(*)(double, struct baz)`
float result = (*(float(*)(double, struct baz))map["foo"])(3.14159, (struct baz){ /*whatever*/});
As you see, it is no problem to call any type of function that way, without restricting to variadic ones. However, this approach is very error prone as you completely do away with the safety provided by the type system, and your casts must be 100% correct. Weird stuff may happen if you don't. That's the same problem as with using boost::any.
I'm trying to create a function that will store and repeat another function given as a parameter for a specific amount of time or repeats given.
But when you want to pass a function as a parameter you have to know all of its parameters before hand.
How would I do if I wanted to pass the function as one parameter, and the parameters as another?
void AddTimer(float time, int repeats, void (*func), params); // I know params has no type and that (*func) is missing parameters but it is just to show you what I mean
Thanks in advance
The best that you can do is use std::function or boost::function as argument, together with std::bind or boost::bind to, well, bind the arguments with the function:
void foo() { std::cout << "foo" << std::endl; }
void bar( int x ) { std::cout << "bar(" << x << ")" << std::endl; }
struct test {
void foo() { std::cout << "test::foo" << std::endl; }
};
void call( int times, boost::function< void() > f )
{
for ( int i = 0; i < times; ++i )
f();
}
int main() {
call( 1, &foo ); // no need to bind any argument
call( 2, boost::bind( &bar, 5 ) );
test t;
call( 1, boost::bind( &test::foo, &t ) ); // note the &t
}
Note that there is something inherently wrong with passing a fully generic function pointer: how do you use it? How would the body of the calling function look like to be able to pass an undefined number of arguments of unknown types? That is what the bind templates resolve, they create a class functor that stores the function pointer (concrete function pointer) together with copies of the arguments to use when calling (note the &t in the example so that the pointer and not the object is copied). The result of the bind is a functor that can be called through a known interface, in this case it can be bound inside a function< void() > and called with no arguments.
dribeas' answer is correct as far as modern C++ is concerned.
For the sake of interest, there's also a simple lo-tech solution from the C world that as far as it goes, works in C++. Instead of allowing arbitrary parameters, define the function as void (*func)(void*), and make "params" void*. It's then the caller's job to define some struct that will contain the parameters, and manage its lifecycle. Usually the caller would also write a simple wrapper to the function that's really needed to be called:
void myfunc(int, float); // defined elsewhere
typedef struct {
int foo;
float bar;
} myfunc_params;
void myfunc_wrapper(void *p) {
myfunc_params *params = (myfunc_params *)p;
myfunc(params->foo, params->bar);
}
int main() {
myfunc_params x = {1, 2};
AddTimer(23, 5, myfunc_wrapper, &x);
sleep(23*5 + 1);
}
In practice you want to "fire and forget" timers, so if you use this scheme you may also need a way for the timer manage to free the userdata pointer once all firings have completed.
Obviously this has limited type safety. In principle in shouldn't matter, because whoever supplies the function pointer and user data pointer shouldn't have a great deal of difficulty ensuring that they match. In practice of course people find ways to write bugs, and ways to blame you because their compiler didn't tell them about the bugs ;-)
It's just an example how you could pass function pointer to another function, and then call it:
void AddTimer(float time, int repeats, void (*func)(int), int params)
{
//call the func
func(params);
}
void myfunction(int param)
{
//...
}
AddTimer(1000.0, 10, myfunction, 10);
Similarly, you can write your code if your function takes different type or/and numbers of parameters!
If there's really no rules about the function pointer at all, just use void*.
In C++11, things get really simple - you get everything you need to implement your timers.
The most concise way of passing bound function calls is by passing a functor generated using lambda syntax, e.g.: []{ std::cout << "Hello, world!" << std::endl; }. An object thus generated has a type known only to the compiler, but the type is convertible to std::function<void()>.
#include <functional>
#include <list>
#include <chrono>
#include <thread>
#include <iostream>
template <typename Clock = std::chrono::high_resolution_clock>
class Timers {
public:
using clock = Clock;
using duration = typename clock::duration;
using time_point = typename clock::time_point;
private:
struct Timer {
duration const period;
std::function<void()> const call;
int repeats;
time_point next;
Timer(duration $period, int $repeats, std::function<void()> && $call) :
period($period), call(std::move($call)), repeats($repeats) {}
};
std::list<Timer> m_timers;
public:
Timers() {}
Timers(const Timers &) = delete;
Timers & operator=(const Timers &) = delete;
template <typename C> void add(std::chrono::milliseconds period,
int repeats, C && callable)
{
if (repeats) m_timers.push_back(Timer(period, repeats, callable));
}
enum class Missed { Skip, Emit };
void run(Missed missed = Missed::Emit) {
for (auto & timer : m_timers) timer.next = clock::now() + timer.period;
while (! m_timers.empty()) {
auto next = time_point::max();
auto ti = std::begin(m_timers);
while (ti != std::end(m_timers)) {
while (ti->next <= clock::now()) {
ti->call();
if (--ti->repeats <= 0) {
ti = m_timers.erase(ti);
continue;
}
do {
ti->next += ti->period;
} while (missed == Missed::Skip && ti->next <= clock::now());
}
next = std::min(next, ti->next);
++ ti;
}
if (! m_timers.empty()) std::this_thread::sleep_until(next);
}
}
};
int main(void)
{
Timers<> timers;
using ms = std::chrono::milliseconds;
timers.add(ms(1000), 2, []{ std::cout << "Hello, world!" << std::endl; });
timers.add(ms(100), 20, []{ std::cout << "*" << std::endl; });
timers.run();
std::cout << std::endl;
return 0;
}