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
Related
Is it possible to have callback to member of template class, as depicted above? I mean, I have some template class, there is defined object of another (non-template) class. That object has another member function. I would like to invoke from that member function the member function of template class. Is it feasible?
This is how I understand the problem. A class called 'some_class' (MyAlgorithm) supposed to have a reference to template (AlgorithmConsumer). Since 'some_class' requires only one method, the easiest way is to pass a reference to the function, something like this:
#include <iostream>
#include <functional>
class MyAlgorithm
{
std::function<void()> prepare;
public:
explicit MyAlgorithm(std::function<void()> prepare)
: prepare{prepare}
{}
void do_something()
{
if (prepare)
{
prepare();
}
std::cout << "I did something\n";
}
};
template<typename T>
class AlgorithmConsumer
{
MyAlgorithm algorithm;
public:
AlgorithmConsumer()
: algorithm([this](){prepare();})
{}
void prepare()
{
std::cout << "Preparing...\n";
}
void execute()
{
algorithm.do_something();
}
};
int main()
{
AlgorithmConsumer<int> ac;
ac.execute();
return 0;
}
Hope, this solves your problem.
Here's one way to do it without using std::function
struct B{
template<class T>
void CallTemplateFun(void (T::*funPtr)(), T& instance){
(instance.*funPtr)();
}
};
template<typename T>
class A{
T t;
B b;
public:
A(T v) : t(v){}
void print(){ std::cout << t << std::endl ; }
};
int main(
{
A<int> ai(5);
B b;
b.CallTemplateFun(&A<int>::print, ai);
A<float> af(3.1428f);
b.CallTemplateFun(&A<float>::print, af);
return 0;
}
Below is the code
#include <iostream>
#include <pthread.h>
using namespace std;
class Base
{
private:
public:
void *threadCall1( void * value)
{
cout<<"inside threadCall1"<<endl;
}
protected:
};
class Derived
{
private:
public:
void *threadCall2 ();
protected:
};
void *Derived::threadCall2()
{
cout<<"inside threadCall2"<<endl;
}
int main ()
{
int k = 2;
pthread_t t1;
cout<<"inside main"<<endl;
Base *b = new Base();
pthread_create(&t1,NULL,&b->threadCall1,(void *)k);
return 0;
}
Error
main.cc: In function int main()': main.cc:46: error: ISO C++ forbids
taking the address of a bound member function to form a pointer to
member function. Say&Base::threadCall1' main.cc:46: error: cannot
convert void*(Base::*)(void*)' tovoid*()(void)' for argument 3'
toint pthread_create(pthread_t*, const pthread_attr_t*,
void*()(void), void*)'
I agree C++ forbids this call but is there any way I can call a class member function using posix thread
You can do this via a function that dispatches the work accordingly:
#include <iostream>
#include <pthread.h>
struct Base {
virtual void work() {
std::cout << "Base::work()\n";
}
virtual ~Base() {}
};
struct Derived : public Base {
void work() override {
std::cout << "Derived::work()\n";
}
};
void* thread_adapter(void* obj) {
Base* p = static_cast<Base*>(obj);
p->work();
return nullptr;
}
int main() {
Derived d;
pthread_t thread;
pthread_create(&thread, nullptr, thread_adapter, &d);
pthread_join(thread, nullptr);
}
Live example
pthread_create accepts a pointer to arbitrary data for the thread function. Pass the address of your object, and use a forwarding function such as the thread_adapter defined above. Inside the adapter function, you can static_cast the argument back to a Base* inside your thread function and invoke the member function as desired.
However, you may want to look into the std::thread library, which supports such operations in a more natural way:
#include <iostream>
#include <thread>
struct Base {
virtual void work() {
std::cout << "Base::work()\n";
}
virtual ~Base() {}
};
struct Derived : public Base {
void work() override {
std::cout << "Derived::work()\n";
}
};
int main() {
Derived d;
std::thread t(&Base::work, d);
t.join();
}
Live example
There's no such thing as &b->threadCall1. Fortunately, pthread allows you to pass a void ptr to the class (the one you're filling with k). Pass b as this void ptr to a global (or static member) function that simply calls b->threadCall1(); then move k to an attribute of Base instead of an argument of Base::threadCall1().
You cannot use pointer to member function as thread routine. Consider to use thead context structure to pass need information to the thead routine:
struct thread_context {
Base* object;
void (Base::*func)(void*);
};
void *thread_routine(void *arg) {
thread_context* context = static_cast<thread_context*>(arg);
context->object->(*context->func)(nullptr);
...
}
...
thread_context context = {
b1,
&Base::threadCall1
};
pthread_create(&t1,NULL,&thead_routine, &context);
I struggle creating derived classes and passing method pointers from it to the base class, so that a function declared in the base class may call it (call the function of the derived class via interface).
The goal is to create derived classes to bring their own ressources and functions, but the call of a function declared there should be possible by calling one of them in the function the base class provides. For this i need to pass a member function pointer of the derived down to the base class.
Here's what I tried:
class KeyFunction
{
void(*KeyFunction::KeyFuncPtr)() = nullptr; //pointer to a method of this class to store standard behavior for call
public:
KeyFunction(void(*KeyFunction::KeyFunc)()) : KeyFuncPtr(KeyFunc) {} //constructor which takes in standard behavior
void func() //standard call of the function
{
if(KeyFuncPtr)KeyFuncPtr(); //call with ensurance there's something to be called
}
void operator()() //make KeyFunction class callable
{
func();
}
};
class customRessource{
public:
string up = "UP";
string down = "DOWN";
};
class customKeyFunc : public KeyFunction
{
customRessource& r;
public:
void moveup() //possible behavior
{
cout << r.up;
}
void movedown()
{
cout << r.down;
}
customKeyFunc( void(*customKeyFunc::KeyFunc)() ) :KeyFunction( ( void(*KeyFunction::)() ) (KeyFunc) ){}
};
int main()
{
customKeyFunc Up(&(customKeyFunc::moveup)); //setup functions
customKeyFunc Down(&customKeyFunc::movedown);
Up(); //call functions
Down();
getchar();
return 0;
}
The main function at the end shows the supposed way to use the class .
First of all: my types in the constructors of each class go wild (i tried a lot of search about how to write member pointers right but i'm still not stable with the syntax)
Can someone help me get them right ?
Can I even do this (especially casting down member pointers like i did in the customKeyFunc constructor)? Am I aproaching this the right way or do I think too complicated ?
Thank you in advance for your help !
something like this?
#include <functional>
#include <string>
#include <iostream>
class customResource{
public:
const std::string up = "UP";
const std::string down = "DOWN";
};
class customKeyFunc
{
const customResource& r;
public:
customKeyFunc(const customResource& r) : r(r) {}
void moveup() //possible behavior
{
std::cout << r.up;
}
void movedown()
{
std::cout << r.down;
}
};
int main()
{
customResource r;
customKeyFunc f(r);
auto Up = std::function<void()>(std::bind(&customKeyFunc::moveup, f));
auto Down = std::function<void()>(std::bind(&customKeyFunc::movedown, f));
Up(); //call functions
Down();
return 0;
}
std::function<void()> is a polymorphic functor which will copy any object that:
is movable or copyable, and
implements void operator()
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();
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.