My intention is to design event callback model in network communication,the event callback includes "recv,send,accept,shutdown..."
class client
{
public:
template<typename F1>
void bind_recv(F1 && f)
{
// How to save the parameter of bind_recv function in _recv_callback member variable ?
_recv_callback = f;
}
// bind_send
// bind_accept
// bind_shutdown
// ...
protected:
void notify_recv()
{
_recv_callback();
}
// notify_send
// ...
// How to declare the type of these variable ?
F1 _recv_callback;
// F2 _send_callback;
// ...
};
int main()
{
client c;
c.bind_recv([](uint8_t * data, size_t len)
{
});
return(0);
}
I need to save callbacks and call them at the right time, but the parameters of each callback function are different, so how do I save them?
I guess maybe my thinking is wrong, so how can I change the design to meet this requirement?
Related
I'm new in C++. I'm trying to do clickable button with OpenGL. I work for add callback function for each button for 2 days, I tried many methods I found but I can't do this. My below codes are giving memory error. Where is my mistake?
main.h
#include <vector>
class Button {
public:
// Storage Vector
static std::vector<Button> Buttons;
// typedef Function
typedef void (*pointerFunction)();
// Constructor
Button(/*Parameters*/);
// Setting Callback
void setCallBack(void(*function)());
// Callback pointer
pointerFunction callback;
int value{ 4 };
};
main.cpp
#include <iostream>
#include "main.h"
std::vector<Button> Button::Buttons;
Button::Button(/*Parameters*/) {
// ...
Button::Buttons.push_back(*this);
}
void Button::setCallBack(void(*function)()) {
this->callback = function;
this->callback(); // Here is work!
}
void testFunction() {
std::cout << "Test\n";
}
void createMember() {
Button classMember;
classMember.setCallBack(&testFunction);
}
int main() {
createMember();
for (Button& button : Button::Buttons) {
std::cout << button.value; // I can access this value.
button.callback(); // But here is give memory error!
}
return 0;
}
Within this function
void createMember() {
Button classMember;
classMember.setCallBack(&testFunction);
}
there are two things that are being doing. The first one is creating the local object classMember. The called construcfor pushes a copy of the object inside the vector Buttons. The data member callback of the copy was not initialized.
It is the data member callback of the .local object classMember that was initialized after its copy was pushed on the vector.
Rewrite the function at least like
void createMember() {
Button classMember;
Button::Buttons.back().setCallBack(&testFunction);
}
You should initialize all data members for example using in particular the literal nullptr if a corresponding initializer was not explicitly supplied. In this case you will be able to check whether a data member of a pointer type is equal to nullptr or stores an actual value.
Your createMember function don't work as you expect.
void createMember() {
Button classMember;
classMember.setCallBack(&testFunction);
}
Creates a local object that will be destroyed at function exit.
You can do it like this (though I don't think it is a good solution.)
Button & createMember() {
static Button classMember;
classMember.setCallBack(&testFunction);
return classMemeber;
}
A better solution:
std::vector<Button> Button::Buttons;
int main() {
Button b;
for (Button& button : Button::Buttons) {
button.setCallBack(testFunction);
std::cout << button.value; // I can access this value.
button.callback(); // But here is give memory error!
}
return 0;
}
Note that you have to defile Button::Buttons somewhere as it is a static member This was correct in your code, I overlooked it.
And, to add at least a Button, you have to create one to be added to the vector.
Ouput:
Test
4Test
You are calling testFunction twice, at setCallBack and in the loop.
(I've added a newline.)
If as the createMember function name suggest, you want to call that to create each new element, you could pass the function pointer in constructor. If it is trivially copyable like is in your example (no pointers or resource allocation in the class) you can just create the instance and the vector copy will be fine.
Button::Button(pointerFunction f) : callback (f) {
// ...
Button::Buttons.push_back(*this);
}
void createMember() {
Button classMember (testFunction);
}
int main() {
createMember ();
for (Button& button : Button::Buttons) {
std::cout << button.value; // I can access this value.
button.callback(); // But here is give memory error!
}
}
I don't think this is a good design for anything real, though.
Your mistake is that you create a local object, push the copy of it into the vector, put the callback address to the original object, and then destroy the original object. Well, you can put the callback address as the constructor argument, then the copy would have it.
// Constructor
Button(void(*function)(), /*Parameters*/) : callback{function} {
Button::Buttons.push_back(*this);
}
But I would recommend to add a static function to the Button class which is responsible for creation a Button object and returning reference to it. This is also eliminate unnecessary creation/deletion of temporary objects.
#include <iostream>
#include <vector>
class Button {
public:
// Storage Vector
static std::vector<Button> Buttons;
// typedef Function
typedef void (*pointerFunction)();
// Constructor
Button(/*Parameters*/);
// Setting Callback
void setCallBack(void(*function)());
// Callback pointer
pointerFunction callback;
template<class... U>
static Button& createButton(U&&... u) {
return Buttons.emplace_back(std::forward<U>(u)...);
}
int value{ 4 };
};
std::vector<Button> Button::Buttons;
Button::Button(/*Parameters*/) {
// ...
Button::Buttons.push_back(*this);
}
void Button::setCallBack(void(*function)()) {
this->callback = function;
this->callback(); // Here is work!
}
void testFunction() {
std::cout << "Test\n";
}
void createMember() {
auto &classMember = Button::createButton(/**/);
//Button classMember;
classMember.setCallBack(&testFunction);
}
int main() {
createMember();
for (Button& button : Button::Buttons) {
std::cout << button.value;
button.callback();
}
return 0;
}
I want to do a member function that will call every X seconds. I did a little prototype that can handle non member function, but I don't know if I did it well, and I can't handle both member function and non member function.
I have an Event object, which handle the function and the delay, with a basic timer, to detect when we need to run the function:
typedef void (*ScheduleFunction)(float dt);
class Event
{
private:
ScheduleFunction m_Func;
double m_Timer;
double m_Delay;
public:
Event(ScheduleFunction function, double delay)
{
m_Func = function;
m_Delay = delay;
}
void Call(float dt)
{
m_Timer += dt;
if (m_Timer >= m_Delay)
{
m_Func(dt);
m_Timer = 0.0;
}
}
};
Then, I have another object that call every frames each function into a vector<Event>:
class Handler
{
private:
void m_MemberFunction(float dt)
{
std::cout << "A member function." << std::endl;
}
std::vector<Event> m_ScheduleItems;
public:
Handler()
{
// This will not compile, because the function expect a non member function
Schedule(&Handler::m_MemberFunction, 1.0);
}
void CallScheduledFunctions(float dt)
{
for (std::vector<Event>::iterator it = m_ScheduleItems.begin(); it != m_ScheduleItems.end(); ++it)
{
it->Call(dt);
}
}
void Schedule(ScheduleFunction func, double delay)
{
Event event(func, delay);
m_ScheduleItems.push_back(event);
}
void Unschedule()
{
// TODO
}
};
As you can see, I have a function Schedule that register new Event. But right now, it only handle non member function. Is there a way that I can handle non member function and member function, not only from the Handler but also on all others objects?
If there is no way, how can I achieve this?
Using std::function is the way to go. Anything that can be called can be transformed/wrapped into an std::function.
In your case, you could write your Event constructor like this:
Event(std::function<void(float)>, double delay);
And you can call this with a standalone function, a functor or a lambda.
Some examples:
// declaration
auto myDummyFunction (float) -> void;
// Calling the constructor
auto event = Event(myDummyFunction,1.0);
If we want to pass a member function, just use a lambda:
// declaration of the class with the member function
class SomeOtherClass
{
public:
auto someMethod(float) -> void;
};
// Calling the constructor
auto someOtherClass = SomeOtherClass{};
auto event = Event([&someOtherClass](float f){someOtherClass.someMethod(v)},1.0);
In general I find lambda's more readable and flexible than the std::bind approach. As far as I can remember, it's advised (was it Herb or Scott?) not to use std::bind anymore, but to use lambda's instead.
UPDATE 1
Added "call any object's members" below.
BRIEF
I recommend using std::function and std::bind. But remind that std::function has some overhead due to the internal mechanisms!
std::function is very powerful as there are many things you can store in it.
Important:
Using a function-pointer only approach is possible, but would cause some code and complexity if you must retain the simple unified interface.
EXAMPLE
#include <functional>
using ScheduleFunction_t = std::function<void(float)>;
class Event {
private:
ScheduleFunction_t
m_Func;
double
m_Timer,
m_Delay;
public:
Event(
ScheduleFunction_t const&function,
double delay)
: m_Func(function)
, m_Delay(delay)
{ }
void Call(float dt) {
m_Timer += dt;
if (m_Timer >= m_Delay)
{
// Important, if you do not assert in the constructor, check if the fn is valid...
// The ctr shouldn't throw on runtime assert fail... memory leak and incpomplete construction...
if(m_Func)
m_Func(dt);
m_Timer = 0.0;
}
}
};
As you can see, including the <functional> header will give you the template std::function<R(Args...)>, where R is the return type and Args... a comma separated list of fully qualified argument types.
void g_freeFunction(float f) {
std::cout << "Globally floating for " << f << "ms" << std::endl;
}
class Handler {
private:
void m_MemberFunction(float dt) {
std::cout << "Floating around with " << dt << " m/s" << std::endl;
}
std::vector<Event> m_ScheduleItems;
public:
Handler() {
// Bind member function
Schedule<Handler, &Handler::m_MemberFunction>(this);
// Or free
Schedule(&g_freeFunction);
// Or lambda
Schedule([](float f) -> void { std::cout << "Weeeeeeeh...." << std::endl; });
}
void CallScheduledFunctions(float dt)
{
for(Event& e : m_ScheduleItems)
e.Call(dt);
}
template <typename TClass, void(TClass::*TFunc)(float)>
void Schedule(
TClass *const pInstance,
double delay = 0.0)
{
m_ScheduleItems.emplace_back(std::bind(TFunc, pInstance, std::placeholders::_1), delay); // Create in place at the end of vector.
}
void Schedule(
ScheduleFunction_t fn,
double delay = 0.0)
{
m_ScheduleItems.emplace_back(fn, delay); // Create in place at the end of vector.
}
void Unschedule() { /* TODO */ }
};
This way you can now bind almost whatever you want. :D
Update:
The Schedule-function can not be called for any other type that has a matching public method, e.g.:
struct Test {
void foo(float f) {
std::cout << "TEST ME!" << std::endl;
}
};
int main()
{
Test t={};
Handler h = Handler();
h.Schedule<Test, &Test::foo>(&t);
for(uint32_t k=0; k < 32; ++k)
h.CallScheduledFunctions(k);
}
RESOURCES
http://en.cppreference.com/w/cpp/utility/functional
http://en.cppreference.com/w/cpp/utility/functional/function
http://en.cppreference.com/w/cpp/utility/functional/bind
WORKING EXAMPLE
http://cpp.sh/7uluut
I want to have objects with one method which calls a function (but every object should have a different function to call). I will try to show you what I mean by showing an example:
class Human
{
public:
void setMyFunction(void func); // specify which function to call
void callMyFunction(); // Call the specified function
};
void Human::setMyFunction(void func) // ''
{
myFunction = func;
}
void Human::callMyFunction() // ''
{
myFunction();
}
void someRandomFunction() // A random function
{
// Some random code
}
int main()
{
Human Lisa; // Create Object
Lisa.setMyFunction(); // Set the function for that object
Lisa.callMyFunction(); // Call the function specified earlier
}
This code (obviously) doesn't work but I hope you understand what I am trying to accomplish.
MfG, TPRammus
You might use std::function.
#include <functional>
class Human
{
std::function<void()> mFunc;
public:
void setMyFunction(std::function<void()> func) { mFunc = func; }
void callMyFunction() { if (mFunc) mFunc(); }
};
Demo
I would suggest using a simple function pointer. Just do this:
class Human
{
public:
using func_t = void (*)();
void setMyFunction(func_t f) {
func = f;
}
void callMyFunction() {
func();
}
private:
func_t func;
};
The reasons why one might prefer function pointers to std::function are:
Performance. Calling std::function tends to be slower, than calling a function by pointer.
std::function needs truly ugly syntax when one needs to bind it to an overloaded function.
Example:
void foo();
void foo(int x = 0);
void check() {
Human h;
h.setMyFunction(&foo);
}
Will fail to compile.
I am toying with this idea for a while but cant seem to wrap my head around it.
Basically what I want to do is create a general Timer class that times all the functions that are passed to it. Averaging it when the same function is called multiple times so it has to store it somehow. It should therefore use the function name to store the task and average it when it occurs more than once.
Pseudoish code of what it should look like.
Class FunctionTaks
{
std::string d_name;
double d_execution_time;
}
Class Timer
{
private:
std::vector<FunctionTask> d_tasks;
public:
template <typename Function, typename ReturnType>
ReturnType time(Function f)
{
// check if function f is timed for first time
// start timer
// run function f
auto r = f.invoke();
// stop timer
// store function name and time, average if more than once
// return whatever f should return
return r;
}
void report() const;
}
I dont really know how to do this, especially when Function f has a different amount of arguments.
Timer t;
t.time(foo());
t.time(bar());
t.time(foo());
t.report();
I basically have a few core issues.
How to let a function wrapper return the same type that the injected code is suppose to return.
How to obtain the function name that is being injected.
The wrapper should not be limited by arguments passed on to the injected function. How to give the injected function the freedom of arguments.
On the other hand I dont really care about the arguments and return type, the wrapper should simply run the injected function as is and perform some timings and then return whatever the injected function is suppose to return.
C++11 but why templates? You need lambda expressions:
typedef void(*TimerFunction)();
void time(TimerFunction fun) {
// start timer
fun();
// stop timer
}
int fun1() { return 1; }
int fun2() { return 2; }
string fun3() { return string("Test"); }
main() {
int ret1, ret2;
string ret3;
t.time([&ret1]() { ret1 = fun1(); });
t.time([&ret2]() { ret2 = fun2(); });
t.time([&ret3]() { ret3 = fun3(); });
}
That's the concept. For details: C++ lambda with captures as a function pointer
With C++11 you can use variable template parameters:
class TimerFoo {
public:
template <class Foo, class... Args> TimerFoo(Foo foo, Args... args) {
// ... start timer
foo(args...);
// ... stop timer
}
};
And use e.g.:
TimerFoo tf = TimerFoo(foo, 1, 2, 3);
Ofcourse you need some field in TimerFoo that will store the measured time...
Edit:
To be able to return a value of your function using this approach you could change the above code to:
#include <iostream>
using namespace std;
class TimerFoo {
public:
template <class Foo, class... Args> auto run(Foo foo, Args... args) -> decltype(foo(args...)) {
// ... start timer
auto result = foo(args...);
// ... stop timer
return result;
}
};
int foo(int a, int b) {
return 2;
}
int main() {
TimerFoo tf;
cout << tf.run(foo, 1, 2) << endl; // output: 2
}
I am trying to write a program that will execute a function based on a string I fetch from a database.
Basically what I do is:
// Create an enum
enum AFunc{
invalidFunction,
function2,
function3
}
// have a class handling the functions
struct A
{
static AFunc resolveStringToFunction(std::string) {...}
template<int T>
void execute(...)
{
// this may not be called = invalidFunction
}
template<>
void execute<1> (...)
{
// do stuff = function1
}
template<>
void execute<2> (...)
{
// do stuff = function2
}
};
In my application i do this:
A a;
std::string funcString = getFromDatabase (...) // Not really, but this is abstract
const AFunc funcType = A::resolveStringToFunction(funcString);
a.execute<funcType>(...);
The problem here is that the compiler does not accept the dynamic calling of a template function, because (as I understood it) it needs to know which function is called by compile time.
Is there any way around this?
Is there a better solution to this problem? Maybe a design pattern?
namespace afunc // dont pollute global namespace
{
typedef std::function<void(...)> aFunc;
static function1(...)
{
// do stuff
}
static function2(...)
{
// do stuff
}
const std::unordered_map<std::string, aFunc> functions (
{{"function1", &function1},{"function2", &function2}} ); // afunc
And it is called by the following code:
std::string funcString = getFromDatabase (...) // Not really, but this is abstract
afunc::functions.at(funcString)(...) // at because the map is const, so it's even threadsafe