I'm trying to store a callback in a class. Currently, I do something like this:
struct Callback {
Callback (std::function<void ()> func) : func_ (func){}
void call() const { func(); }
private:
std::function<void ()> func_;
};
As you can see, only a specific type of function (currently no return and no parameters) can be used.
Is there any way I could use such a class like this, where I pass it what to call it with?
void increment (int &n) {
++n;
}
int main() {
int someNum = 5;
Callback callback (increment, someNum); //will call `increment (someNum);`
}
I was thinking to use a parameter pack to store the arguments, and a typename to store the return type, and then making an std::function<ReturnType (Args)> callback_ sort of thing, and calling it with something like callback_ (givenArgs...);. I'm not really knowledgeable enough on templates to do this, however, or even figure out if it's possible.
The real use I'd be getting out of this (at least right now) is for a timer, but perhaps making a small generic_function<> class that wraps an std::function<> would help more. For this example, though, a timer that pauses and unpauses every 2 seconds:
void togglePause (Countdown &c) {
c.togglePause();
}
int main() {
Countdown main (10000); //create countdown of 10s
Countdown delay (2000, togglePause, main); //this one calls func when expired
for (; !main.expired();) { //go while unpaused time < 10s
delay.wait().reset(); //wait 2s, call callback, reset back to 2s
}
}
Of course this can be applied to other concepts as well, but I'm not sure how to go about attaining this syntax in the first place. I can build two different forms in case the return type is void just fine from an unrelated previous question, but storing a function with any number and types of arguments confuses me. If it's possible, how can I use syntax like this? If not, how close would the syntax be?
I think you just want to use std::bind to convert your function with an argument into a function taking no arguments:
int main() {
int someNum = 5;
std::function<void (void)> boundFunc = std::bind(increment, std::ref(someNum));
Callback callback (boundFunc); //will call `increment (someNum);`
}
Note that you need the std::ref to ensure that someNum is passed by reference and that you need to make sure that someNum stays in scope longer than the callback.
Related
(Title edited to clarify intent.
Original Title: "Can I heap-allocate a va_list to use it later?")
I'm trying to develop a scripting system for my game that allows me to look at all functions which will be called on a future frame and what arguments they will take. Since the args these functions take aren't all the same, I figured the best approach would be to make a struct containing an unwrapper function that takes a va_list, and a va_list to be passed to it. Each unwrapper function just takes the va_list, separates it back into multiple variables, and passes it to a corresponding real function. Then each script has a queue of those structs to be executed on a given frame.
Here's the script class:
class MoveScript {
public:
MoveScript();
MoveScript(std::string name, std::function<void()> move_script);
void activate(); //Clear the ScriptFrame queue, then call move_script()
void execute(float frame); //Checks if the front ScriptFrame is set to this frame. If it is, then call its execute function and remove it from the queue
std::string name;
std::queue<ScriptFrame> frames;
private:
std::function<void()> move_script{ []() {} }; //Runs whenever a new script is activated, populates the ScriptFrame queue
};
Here's the ScriptFrame class:
class ScriptFrame {
public:
ScriptFrame();
ScriptFrame(float frame);
void execute(); //Executes each function_call in the queue with its corresponding function_arg
float frame;
std::queue<std::function<void(ScriptArg)>> function_calls;
std::queue<ScriptArg> function_args;
};
Here's a ScriptArg:
struct ScriptArg {
ScriptArg();
ScriptArg(int num_args, std::va_list va);
void destroy(); //Call va_end() so I don't have to do it within the unwrapper funcs
int num_args;
std::va_list va;
};
And here's an example of all of this in practice
script("wait", [this]() {
execute_frame(0, [this]() {
push_function(&BattleObject::SET_RATE, 1, 0.5);
});
});
void BattleObject::SET_RATE(ScriptArg args) {
UNWRAP(rate, float);
set_rate(rate);
}
Where script initializes a MoveScript and adds it to a table, execute_frame creates a new ScriptFrame to execute on the given frame, push_function pushes the unwrapper function and a va_list generated by the args to the ScriptFrame's respective queues, and UNWRAP is a macro that expands to float rate = va_arg(args.va, float);
As I’m sure you can already tell, this code doesn’t work because of how a va_list becomes invalid after the function which called va_start returns. I found another question about it but couldn’t find any suggestions that I figured could work. I’ve seen stuff about storing a void* instead of va_list and getting the args directly within push_function, but since the args passed can be of different types, I don’t think there’s any way for me to safely use va_arg at that point. So I was wondering, if I heap-allocate the va_list, will that allow me to store it properly, or does it become invalidated as soon as the function which takes the ellipsis goes out of scope? If it does, can I possibly store the ellipsis directly instead of a va_list, then create a va_list in the unwrapper function? Or just generally if there’s a better way to accomplish my goal, what would that be? Let me know if there’s any other info I should provide.
Thanks!
Update: I tried tuples to store the data as a few answers suggested, but that didn't work because I needed to be able to properly index them while the function was still being wrapped, at which point the number and types of args were still unknown. Due to how templates work, I couldn't find a way to store the entire tuple in the ScriptArg struct either (Note: It's entirely possible that all of this was possible to work around and I just couldn't figure it out, but either way I found a way to handle it without using tuples which works for my purposes).
In any case, I managed to accomplish what I was looking for using a queue of std::any instead of a va_list, and populating the queue with all of the variadic arguments the function took. Handling the variadic args using a tuple still didn't seem to work, but as it turns out, I could just use a vector instead. Here's what the full process looks like.
ScriptArg declaration:
struct ScriptArg {
ScriptArg();
ScriptArg(int num_args, std::queue<std::any> args);
std::any get_arg(); //Get the argument at the front of the queue, pop it and return the argument
void pop();
int num_args;
std::queue<std::any> args;
};
The UNWRAP macros:
//Declares a variable of the given type and extracts its value from the queue
#define UNWRAP(var_name, type) type var_name = std::any_cast<type>(args.get_arg());
//Same as the above, but for variables that were already declared
#define UNWRAP_NO_DECL(var_name, type) var_name = std::any_cast<type>(args.get_arg());
Wrapping a member function:
template<typename ...T>
void push_function(void (BattleObject::* function)(ScriptArg), T... args) {
std::queue<std::any> queue = extract_variadic_to_queue(args...);
ScriptArg sa(sizeof...(args), queue);
active_script_frame.function_calls.push(std::bind(function, this, std::placeholders::_1)); //I believe I could also just bind the arguments directly instead of putting a placeholder here, but since I need to store the arguments separately for other reasons, this is fine.
active_script_frame.function_args.push(sa);
}
template<typename ...T>
std::queue<std::any> extract_variadic_to_queue_impl(const T&... args) {
std::vector<std::any> vec = { args... };
std::queue<std::any> ret;
for (int i = 0, max = vec.size(); i < max; i++) {
ret.push(vec[i]);
}
return ret;
}
template<typename ...T>
std::queue<std::any> extract_variadic_to_queue(T... args) {
return extract_variadic_to_queue_impl(std::any(args)...);
}
And besides the fact that I need to unwrap the float as a double due to std::any's type promotion, the unwrapping function itself looks exactly the same:
void BattleObject::SET_RATE(ScriptArg args) {
UNWRAP(rate, double);
set_rate(rate);
}
I'm still not sure if there's a more efficient way to handle this, but it's overall the simplest method I could find for storing future function arguments without needing to know their quantities and type until they were actually called, which was my end goal. Sorry for not making that more clear in the initial question, but I appreciate you all steering me in the right direction and away from va_lists. Thanks!
I am trying to generalize my benchmarking function, by having it receive the function to benchmark as the first parameter and the number of iterations as the second.
But since the function to benchmark needs to receive additional parameters, I thought I would fill in the parameters in the body of a lambda function and pass that to the benchmarking function. (I think that is called currying?)
Anyway I can not get it to compile:
main.cpp:43:62: error: invalid initialization of non-const reference of type ‘std::function<double*()>&’ from an rvalue of type ‘main(int, char**)::<lambda()>’
bench::bench([=](){rng::gpu_r_exp((int) 10e6, lambda);}, 50);
The function declaration looks like this:
void bench(std::function<double*()>& funct_to_bench, int repeats);
and I use it like this:
bench::bench([=](){rng::gpu_r_exp((int) 10e6, lambda);}, 50);
Since the compiler bickers about non-const again, I should maybe add, that gpu_r_exp utilizes a global variable which stores the rngState (it also did not like non-const parameters in gpu_r_exp).
I am really stuck. I just want to fill in the parameters and pass the pre-prepared function handle to the benchmarking function, so that it can wrap a timer with a progress bar around it.
EDIT: I should add that the parameter called lambda is a double, which is the parameter of the exponential distribution and has nothing to do with the lambda function.
Given that the benchmark wrapper is small, it doesn't make sense to worry about what's passed in, or whether it can be converted to std::function. Just take what comes and as long as it can be called, you're golden:
template <typename Fun>
void benchmarkCallable(size_t iterations, Fun &&callable)
{
//...
while (iterations--)
callable();
//..
}
If you worry that the //... sections are getting unwieldy, you can factor them out into a class:
class ScopedBenchmark {
// start time, other state needed, etc.
public:
ScopedBenchmark() { /* capture initial state */ }
~ScopedBenchmark() { /* dump results etc */ }
};
template <typename Fun>
void benchmarkCallable(size_t iterations, Fun &&callable)
{
ScopedBenchmark benchmark;
while (iterations--)
callable();
}
int main()
{
benchmarkCallable(1'000'000, []{ printf("foo!\n"); });
}
I want to call the following function and pass it a function with a parameter. The purpose of that is that it should call the function with my specified parameter so I know what triggered the function (in that case a gpio pin on the Raspberry Pi).
int wiringPiISR( int pin, int edgeType, void (*function)( void ) );
Currently I have:
for ( int i = 0; i < myValues.size(); ++i )
{
int myValue = myValues[ i ];
wiringPiISR( myValue, INT_EDGE_RISING, &myCallback( myValue ) );
}
Though this is giving me the following error:
error: lvalue required as unary ‘&’ operand
Which I can't really understand as to my understanding, myValue is an lvalue or is it not?
Is it what I want do even possible? If so how?
The function wiringPiISR is from a library called wiringPi and I would like to avoid modifying it as much as possible.
You could combine the answers from imreal and Ryan Haining something like this.
std::function<void()> cbfunc;
void myCallback()
{
cbfunc();
}
void myWiringPiISR(int val, int mask, std::function<void()> callback)
{
cbfunc = callback;
wiringPiISR(val, mask, &myCallback);
}
... and then use it...
void myActualCallback(int v)
{
... do something...
}
myWiringPiISR(myValue, INT_EDGE_RISING, std::bind(myActualCallback, myValue));
No need to patch library, and you can use all the bind/function goodness. I'll leave you to find a way around the thread safety issues...
How does it work? Put simply 'std::bind' is binding together a function and it's parameters into a single std:function object which can then be 'called' from the myCallback function which acts as a shim around the callback that you pass. I'd given the callback function a confusing name before, but this edit has hopefully fixed that.
You can "vomit" the function. This doesn't require a user-defined mutable global variable and is thread-safe, unless you have a compiler that supports multiple threads but not per-thread exceptions which would be basically unusable.
myWiringPiISRWrapper(Value value, int edge, std::function<void()> func) {
try {
throw &func;
} catch(...) {
myWiringPiISR(value, edge, [] {
try {
throw;
} catch(std::function<void()>* func) {
(*func)();
}
});
}
}
It's disgusting and slow, but it's totally encapsulated which I think is a worthwhile upside. Note that this only works if the callback is never executed after the call to myWiringPiISR returns. In this case you can of course have a callback with whatever bound state you desire.
If myValue is something you can decide at compile time, you could set it statically and use an intermediate function to pass in.
void myCallbackHelper() {
static constexpr int myValue = 3;
myCallback(myValue);
}
wiringPiISR(myValue, INT_EDGE_RISING, &myCallbackHelper);
If you need to determine myValue at run time, you could still accomplish this, but not really thread-safely.
int& getMyValue() {
static int myValue;
return myValue;
}
void setMyValue(int i) {
getMyValue() = i;
}
void myCallbackHelper() {
myCallback(getMyValue());
}
Then set it and call
setMyValue(3);
wiringPiISR(myValue, INT_EDGE_RISING, &myCallbackHelper);
I looked up wiringPiISR and found that it is some sort of api call, so i am assuming you cannot change it.
Having said that, there is a reason most api-calls with a function-pointer-callback look sort of like this
void setCallback( void (*function)(void* data), void* userdata);
This allows people to cast their struct {blabla} data; to add some userdata, and when the function is called, it is passed along.
So basically, apart from hacking stuff with static variables, you can't pass any arguments.
You need to use std::function and std::bind.
Change your function signature to
int wiringPiISR (int pin, int edgeType, std::function<void()> func);
Inside you can call the callback simply using func()
And your call to:
int myValue = 3;
wiringPiISR(myValue, INT_EDGE_RISING, std::bind(myCallback, myValue));
What this does is create a std::function object (i.e. a callable) that wraps your function and keeps your desired value in its state.
This will only work on C++11 and newer.
If you have c++11, I suggest using std::function - it's quite a bit cleaner.
If not, your function signature is wrong. You want a callback with the type void(int) but your function takes a void()
Say that you define a callback function as such:
typedef std::function<void(float)> Callback;
And you have a function as such:
void ImAFunction(float a)
{
//Do something with a
}
Is there a way to be able to store a function without an argument then pass one to it at a later time?
Such as this:
//Define the Callback storage
Callback storage;
storage = std::bind(ImAFunction, this);
//Do some things
storage(5);
This wont work which I explain with some of my real code below.
I can get close to what I wan't if I bind the value in with the std::bind function. Such as:
//Change
//storage = std::bind(ImAFunction, this);
storage = std::bind(ImAFunction, this, 5.0); //5.0 is a float passed
This works but when I go to pass a value through the function the outcome is whatever I set it to before:
storage(100); //Output is still 5
I am basing the fact that I think this is possible on this article.
http://www.cprogramming.com/tutorial/function-pointers.html
It doesn't use the function or bind functions but it does pass pointer arguments and performs exactly what I need. The reason I don't just skip the bind function is because I am trying to store the function in a class (private) and I can't store it if it's a template because it's created with the class.
The error produced above comes from this code:
struct BindInfo {
Callback keyCallback;
int bindType;
bool isDown;
bool held;
std::string name;
};
template <class T1>
void bindEvent(int bindType, T1* keydownObj, void(T1::*keydownF)(float), std::string name)
{
BindInfo newKeyInfo = { std::bind(keydownF, keydownObj), bindType, false, false, name };
inputBindings.insert(std::pair<int, BindInfo>(BIND_NULL, newKeyInfo));
};
The error is:
No viable conversion from '__bind<void(Main::*&)(float), Main *&>' to 'Callback' (aka 'function<void (float)>'
Is this possible? Thanks in advance.
You can include a placeholder for an unbound argument:
std::bind(&Main::ImAFunction, this, std::placeholders::_1);
If you find that a bit of a mouthful, a lambda might be more readable:
[this](float a){ImAFunction(a);}
It sounds like what you're looking for is a function pointer. While I don't have a lot of experience using them in C++ I have used them in C so: Yes, it is possible. Perhaps something like this:
void (*IAmAFunctionPointer)(float) = &IAmAFunction;
The best way to think about that line is, that IAmAFunctionPointer is a pointer (hence the *), it returns a void, and takes a float. Then later:
float a = 5;
IAmAFunctionPointer(a);
You could even design it so that the callback function is passed into the method (I assume this is what you're looking for).
void DoStuffThenCallback(float a, void (*callback)(float))
{
//DoStuff
callback(a);
}
further reading: http://www.cprogramming.com/tutorial/function-pointers.html
I was thinking about doing a take_timing function that would take the timing of any function passed to it. By any function it means that the arguments this callback takes is unknown by the caller. It would take too the arguments for the callback. But as it doesn't know how to call it, it would take another callback function, the caller of the callback, written by the function user. The stub would be something like this:
void take_timing(
void (*callback)(),
void (*caller(void (*callback)(),void* args_struct),
void* args_struct
)
{
// Start timer
caller(callback,args_struct);
// Stop timer, read timings, record...
}
void some_caller(void (*callback)(),void* args_struct)
{
// Cast "callback" to function signature
// Cast args_struct to some struct with args
// Call the callback with correct args signature
}
So comes my questions:
Is it possible?
Can it use variable arguments list to make it simples? How? I am helpless on this...
Is there a better way of doing it? Or is it just better to do a take_timing for every specific case?
Is there a OOP Design Pattern for this for use with C++?
I myself gave up on this, but put it here out of curiosity, maybe some very useful insights.
Just take a functor as a template argument. Something like:
template<typename F>
nanoseconds take_timing(F f) {
auto start = high_resolution_clock::now();
f();
auto end = high_resolution_clock::now();
return end - start;
}
long long factorial(int i);
take_timing( [](){factorial(20);} ); // wrap call to function taking arguments in zero-argument lambda
You're looking for varargs support, which does exist in ANSI C. A gazillion or so google hits will result if you search for it. Here's one at random: http://www.eskimo.com/~scs/cclass/int/sx11b.html
One way to handle this is to take a boost::bind function object as your parameter:
http://www.boost.org/doc/libs/1_48_0/libs/bind/bind.html
You could hide the fact that closures are involved with macros.