I have the following code that implements a callback. I would like the callback to take some arguments but can only get it to compile with no arguments.
#include <iostream>
#include <string>
#include <functional>
template<typename TDeserialisable>
class Images;
class Analyze;
class X
{
void operator()(...) {}
};
/** Interface for serialising/deserialising types defined by TDeserialisable */
template<typename TDeserialisable>
class IDeserialisable
{
public:
virtual void deserialise(std::function<void()> callback) = 0;
virtual void deserialise(std::function<void(IDeserialisable<TDeserialisable>&)> callback) = 0;
};
class Analyze
{
public:
void operator()()
{
// deserialise
}
void operator()(Images<Analyze>& images)
{
// deserialise
}
};
template<typename TDeserialisable>
class Images : public IDeserialisable<TDeserialisable>
{
private:
virtual void deserialise(std::function<void()> callback)
{
callback();
}
virtual void deserialise(std::function<void(IDeserialisable<TDeserialisable>&)> callback)
{
callback(*this);
}
};
int main()
{
Analyze a;
Images<Analyze> images;
// calls the first overload
static_cast<IDeserialisable<Analyze>&>(images).deserialise(a);
// how do I call the second overload of deserialise?
return 0;
}
How do I call the second overload of deserialise?
You need to specify the input parameter type as a function parameter to the std::function template type. Something like:
std::function<void(Analyze&, Images<Analyze>&)> mf_p = Analyze::operator();
Related
I would like to have the following class setup in a program:
A class that implements a buffer. This buffer, when full, would spawn a thread that makes a callback to handle what to do with the full buffer.
A base class template that includes a buffer object. Implements the callback function, which makes a call to a virtual function defined in a derived class.
A derived class that inherits from base class and implements what to do with the data.
First, the minimal reproducible example:
#include <vector>
#include <iostream>
#include <thread>
template <typename T>
class CallbackBuffer
{
public:
std::vector<T> buffer;
void (*callback)(std::vector<T>);
std::thread writerThread;
CallbackBuffer(int bufferSize = 10)
{
buffer.resize(bufferSize);
}
void setCallback(void (*cb)(std::vector<T>))
{
callback = cb;
}
void writeCall()
{
writerThread = std::thread(callback, buffer);
}
};
template <typename T>
class Base
{
public:
CallbackBuffer<T> buffer;
Base()
{
buffer.setCallback(bufferHandler);
}
void bufferHandler(std::vector<T> v)
{
for(auto &i : v)
{
write(i);
}
}
virtual void write(T i) = 0;
};
class Derived : public Base<int>
{
public:
Derived()
{
}
void write(int i)
{
std::cout << i << std::endl;
}
};
int main()
{
Derived d;
return 0;
}
I'm getting the following compiler error:
error: invalid use of non-static member function ‘void Base<T>::bufferHandler(std::vector<T>) [with T = int]’
So the compiler needs bufferHandler to be static, but if I did that, then I would not have access to the object's members. Is there a way to sort this, or just a horrible idea?
You are passing the class member function so you need to have in your CallbackBuffer class something like:
void (Base<T>::*callback)(std::vector<T>);
// ...
void setCallback(void (Base<T>::*cb)(std::vector<T>)) {
callback = cb;
}
and in Base class:
Base() {
buffer.setCallback(&Base<T>::bufferHandler);
}
Demo
Member function pointers have different type than regular functions, that's why your code does not work. What you may want is using std::function instead of raw pointers:
#include <functional>
//...
std::function<void(std::vector<T>)> callback;
// ...
void setCallback(const std::function<void(std::vector<T>)>& cb) {
callback = cb;
}
and pass it like that:
Base() {
buffer.setCallback([this](auto& vec){ this->bufferHandler(vec); });
}
IMHO this is much more readable and flexible than passing around member pointers
I was able to make the callback work without class templates. But my requirement is to implement callbacks with passing class objects which are in template form. I have written my intent in the main(), but somehow I am unable to make it work.
I cannot use boost and C++11 for my current issue. Any help would be greatly appreciated.
// TestProj.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "glb.h"
#include "Test.h"
#include <iostream>
using namespace std;
class MyCallBack
{
private:
class Callback
{
public:
virtual ~Callback() { }
virtual void call() = 0;
};
template <typename T>
class ClassCallback : public Callback
{
private:
T* object;
void (T::*callback)();
public:
ClassCallback(T* obj, void (T::*clbk)()) : object(obj), callback(clbk) {}
virtual void call() { (object->*callback)(); }
};
private:
Callback* callback;
public:
MyCallBack() : callback(NULL) { }
~MyCallBack() { delete callback; }
template <typename T>
MyCallBack(T* obj, void (T::*clbk)())
{
callback = new ClassCallback<T>(obj,clbk);
}
void operator () ()
{
callback->call();
}
};
typedef enum {
EVENT1 = 1,
EVENT2 = 2,
EVENT3 = 4,
EVENT4 = 8
} MyEvent_t;
template <class EventT>
class EventHandler
{
public:
virtual void on_event(EventT _event) = 0;
};
class MyHandler:public EventHandler<MyEvent_t>{
virtual void on_event(MyEvent_t _event){
switch(_event){
case EVENT1:
break;
case EVENT2:
break;
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
EventHandler<MyEvent_t> *my_handler = new MyHandler();
MyCallBack rcb(my_handler,&MyHandler<MyEvent_t>::on_event);
// to check the callback
rcb();
return 0;
}
Thanks a lot of any leads!!!
The line
MyCallBack rcb(my_handler,&MyHandler<MyEvent_t>::on_event);
is a problem since on_event takes an argument. The member function pointer expected in the constructor of MyCallBack() does not take any arguments.
The following works for me from a compile/build point of view. You'll have to figure out how to make it work for a semantic point of view.
#include <iostream>
using namespace std;
class MyCallBack
{
private:
class Callback
{
public:
virtual ~Callback() { }
virtual void call() = 0;
};
template <typename T>
class ClassCallback : public Callback
{
private:
T* object;
void (T::*callback)();
public:
ClassCallback(T* obj, void (T::*clbk)()) : object(obj), callback(clbk) {}
virtual void call() { (object->*callback)(); }
};
private:
Callback* callback;
public:
MyCallBack() : callback(NULL) { }
~MyCallBack() { delete callback; }
template <typename T>
MyCallBack(T* obj, void (T::*clbk)())
{
callback = new ClassCallback<T>(obj,clbk);
}
void operator () ()
{
callback->call();
}
};
typedef enum {
EVENT1 = 1,
EVENT2 = 2,
EVENT3 = 4,
EVENT4 = 8
} MyEvent_t;
template <class EventT>
class EventHandler
{
public:
void event() { on_event(EventT()); }
virtual void on_event(EventT _event) = 0;
};
class MyHandler:public EventHandler<MyEvent_t>{
virtual void on_event(MyEvent_t _event){
switch(_event){
case EVENT1:
break;
case EVENT2:
break;
default:
break;
}
}
};
int main(int argc, char* argv[])
{
EventHandler<MyEvent_t> *my_handler = new MyHandler();
MyCallBack rcb(my_handler,&EventHandler<MyEvent_t>::event);
// to check the callback
rcb();
return 0;
}
I think what you are trying to achive is the action pattern.
Have a look here: https://en.wikipedia.org/wiki/Command_pattern
And now to the implementation:
#include <iostream>
#include <memory>
struct Action {
virtual void execute() = 0;
};
struct SomeAction : public Action {
void execute() {
std::cout << "SomeAction" << std::endl;
}
};
struct SomeOtherAction : public Action {
void execute() {
std::cout << "SomeOtherAction" << std::endl;
}
};
class EventHandler {
std::unique_ptr<Action> action; // The unique ptr will delete action if the event handler is destroyed
public:
EventHandler() :
action(new SomeAction())
{
}
void setAction(Action* newAction) {
action = std::unique_ptr<Action>(newAction);
}
void eventCalled() {
// This function is invoked from the outside if the event happens
action->execute();
}
};
int main() {
EventHandler eventHandler;
//Some event is called
eventHandler.eventCalled(); // Output "SomeAction"
// We change the action later in time
eventHandler.setAction(new SomeOtherAction());
// Another Event gets called
eventHandler.eventCalled(); // Output "SomeOtherAction"
return 0;
}
I want to be able to perfect forward argument to derived class through base class. The only idea I have is to implement not virtual perfect forwarding function in base class and have virtual functions overloads for lvalues and rvalues. Something like this:
Consider:
#include <iostream>
#include <memory>
#include <string>
class base_t
{
public:
virtual ~base_t() = default;
template<typename T>
void perfect_forward(T&& value)
{
process(std::forward<T>(value));
}
protected:
virtual void process(const std::string& value) = 0;
virtual void process(std::string&& value) = 0;
};
class derived_t : public base_t
{
protected:
void process(const std::string& value) override final
{
std::cout << "derived_t::process(const lvalue&)" << std::endl;
}
void process(std::string&& value) override final
{
std::cout << "derived_t::process(rvalue&&)" << std::endl;
}
};
int main(int argc, const char* argv[])
{
const std::string lvalue;
auto rvalue = []() { return std::string(); };
std::unique_ptr<base_t> base(new derived_t);
base->perfect_forward(lvalue);
base->perfect_forward(rvalue());
}
But this has a little meaning, because instead of template perfect_forward function in base class I can simply provide two overload for virtual process. How I can avoid code duplicate in derived class for process method and use std::forward there through base_t interface?
If you don't want to take the std::string by value, there is an approach using a mixin class, but it requires changing your class hierachy:
template<class D>
class process_mixin : public base_t {
protected:
void process(std::string const& value) override final {
return ((D*)this)->do_process(value);
}
void process(std::string&& value) override final {
return ((D*)this)->do_process(std::move(value));
}
};
class derived_t : public process_mixin<derived_t> {
protected:
template<typename T>
void do_process(T&& value) {
}
friend process_mixin<derived_t>;
};
process_mixin only has to be written once. From then on anything that derives from base_t can instead derive from process_mixin and you get a perfect forwarding interface.
Basically, I need to set a variable outside of the constructor and make it accessible to the entire class.
It would need to work something like this:
#include <iostream>
#include <string>
template <typename MT>
class CallbackFunction
{
void (*func)(MT);
MT *data;
public:
void SetCallbackData (void (*f)(MT), MT *d)
{
func = f;
data = d;
}
void Call()
{
func(data);
}
};
class Callback
{
public:
template <typename T>
void SetCallback(CallbackFunction <T> *func)
{
// Need to make this a class member;
CallbackFunction <T> *CallbackClass = func;
}
void Call()
{
CallbackClass->Call();
}
};
template <typename CT>
Callback *NewCallback(void (*func)(CT), CT *data)
{
Callback *cb;
CallbackFunction <CT> *cf;
cf->SetCallbackData(func, data);
cb->SetCallback <CT> (cf);
return cb;
};
void Call(Callback *CallbackFunc)
{
CallbackFunc->Call();
}
void foo(std::string str)
{
std::cout << str << "\n";
}
int main()
{
std::string *str;
str->append("Hello, World!");
Call( NewCallback(foo, str) );
return 0;
}
More details:
I know it's buggy, and it doesn't compile, I'll sort out those bugs when I find a solution to my problem. Which is:
I need to find a way to declare a template variable inside a member function of the class "Callback". I need to do this because the class "Callback" cannot be a template, it needs to remain a simple class. So because the class "Callback" is not a template, I need to make one of it's member functions a template instead. So that member function can declare a variable of the type defined (with the template) when the function is called, and this variable needs to be accessible to the entire class.
So in a nice list:
class "Callback" cannot be a template,
variable CallbackClass must be accessible to the entire class,
but remain inside of the class.
#include <iostream>
#include <string>
#include <memory>
template <typename MT>
class CallbackFunction
{
typedef void (*func_ptr)(MT);
func_ptr f_ptr;
typedef std::shared_ptr<MT> data_ptr;
data_ptr data_p;
public:
void SetCallbackData (func_ptr f_ptr_, MT *d)
{
f_ptr = f_ptr_;
data_p.reset(d);
}
void Call()
{
if ( f_ptr ) f_ptr(data);
}
};
template<class T>
class Callback
{
public:
template <typename T>
void SetCallback(CallbackFunction <T> *func)
{
f_ptr.reset(func);
}
void Call()
{
if ( f_ptr ) f_ptr->Call();
}
typedef std::shared_ptr<CallbackFunction<T>> func_ptr;
static func_ptr f_ptr;
};
I would implement this using polymorphism. Your programming skills seem good so I will just sketch the direction to solution, feel free to ask for more help if needed.
// your callbackobjects inherit from this class, the sole purpose of this
// class is to provide the Call interface. The derived classes implement
// their custom version of Call().
class CallBackObject{
public:
virtual void Call(){};
};
class Callback
{
CallBackObject *callBackObject;
public:
void SetCallback(CallBackObject *o)
{
callBackObject = o;
}
void Call()
{
callBackObject -> Call();
}
};
Create an abstract interface Callback class and have your CallbackFunction<T> inherit from this. Have your Callback class hold a pointer to this abstract interface. Finally, have your Callback::SetCallback assign func to this pointer.
Here's some code to illustrate the idea:
class ICallback
{
public:
virtual ~ICallback() {}
virtual void Call() = 0;
};
template <typename MT>
class CallbackFunction : public ICallback
{
typedef void (*callback)(MT);
callback myfunc;
MT *data;
public:
CallbackFunction (callback f, MT *d) :
myfunc (f),
data (d)
{}
void Call()
{
if(myfunc && data)
{
myfunc(*data);
}
else throw std::logic_error("Callback function or data is null!");
}
};
Then have Callback hold a ICallback*:
class Callback
{
ICallback *mycallback;
public:
template <typename T>
void SetCallback(CallbackFunction <T> *func)
{
// Need to make this a class member;
// CallbackFunction <T> *CallbackClass = func;
mycallback = func;
}
void Call()
{
mycallback->Call();
}
};
The idea is to make all instantiated templates of CallbackFunction <T> a kind-of ICallback. Now the class using ICallback can take any class CallbackFunction <T> without needing to know what T is.
I have this code:
#ifndef FUNCSTARTER_H
#define FUNCSTARTER_H
#endif // FUNCSTARTER_H
#include <QObject>
class FunctionStarter : public QObject
{
Q_OBJECT
public:
FunctionStarter() {}
virtual ~FunctionStarter() {}
public slots:
void FuncStart(start) {
Start the function
}
};
In the FuncStart function, you would put your function in as a parameter and then it would execute the parameter (aka the function). How would I do this?
either you pass a function pointer, or you define a functor class. A functor class is a class that overloads operator(). This way, the class instance becomes callable as a function.
#include <iostream>
using namespace std;
class Functor {
public:
void operator()(void) {
cout << "functor called" << endl;
}
};
class Executor {
public:
void execute(Functor functor) {
functor();
};
};
int main() {
Functor f;
Executor e;
e.execute(f);
}
You'd pass the function pointer as parameter. This is called a callback.
typedef void(*FunPtr)(); //provide a friendly name for the type
class FunctionStarter : public QObject
{
public:
void FuncStart(FunPtr) { //takes a function pointer as parameter
FunPtr(); //invoke the function
}
};
void foo();
int main()
{
FunctionStarter fs;
fs.FuncStart(&foo); //pass the pointer to the function as parameter
//in C++, the & is optional, put here for clarity
}