I'm attempting to remove boost libraries from my code.
I don't have std::function, and i'm working with C++98, not c++11. I still need to store a vector of simple void Funcs() from different classes.
I'm using a simple template to get the Class and the instance of the function.
But i'd like to replace the need for boost::function and boost::bind.
class App
{
public:
App();
template<class T>
static void AddLoopFunc(void (T::*func)(), T* instance)
{
loop_funcs.push_back(boost::bind(func, instance));
}
static std::vector< boost::function<void()> > loop_funcs;
};
adding a function to the loop
App::AddLoopFunc(&MyClass::Loop, this);
Let's make some type-erasing adaptor for a member function of any class with a given signature.
struct dummy
{
void func() {};
};
typedef void (dummy::*dummyfunc)();
template <class Obj>
void adapt_ptr_mem_func_0(void* obj, dummyfunc func)
{
void (Obj::*realfunc)() = reinterpret_cast<void (Obj::*)()>(func);
Obj* realobj = reinterpret_cast<Obj*>(obj);
(realobj->*realfunc)();
}
You can call a pointer-to-member-function of any class with this. Not in a type safe manner but we will hide this behind a type-safe store front in a moment.
class callback
{
void (dummy::*func)();
void* obj;
void (*adaptor)(void*, void (dummy::*)());
public:
template <class Obj>
callback(Obj* obj, void (Obj::*func)(void)) :
obj(obj), func(reinterpret_cast<dummyfunc>(func)),
adaptor(adapt_ptr_mem_func_0<Obj>) {}
void operator()()
{
adaptor(obj, func);
}
};
The callback constructor accepts an object obj_ and a pointer-to-member-function func_, and makes a type-erased function object that, when called, calls (obj->*func)().
Testing:
struct Moo
{
int m;
Moo (int m) : m(m) {};
void doit() { std::cout << m << "\n"; }
};
int main()
{
Moo moo(42);
callback c(&moo, &Moo::doit);
c();
};
boost::function and boost::bind are available in C++98, no need to replace them.
Related
I want to allow a lambda function to access members of an object. There are 2 classes involved here:
The class I want to access
class D {
public:
void doIt() {};
};
An initializer class for management
template<typename T>
class I {
public:
I(std::function<void ()> f) {
someManager->register(this);
_func = f;
}
void run() {
T* t = new T();
auto fn = std::bind(t, _func);
fn();
}
private:
std::function<void ()> _func;
};
static I<D> _init_([]() {
doIt();
});
Then in someManager I'd call: i->run(). However, the call to doIt() is not accepted. What must be changed to make this compile and work?
A working version with fixes:
class D {
public:
void doIt() {};
};
template<typename T>
class I {
public:
I(std::function<void(D*)> f) {
_func = f;
}
void run() {
T* t = new T();
auto fn = std::bind(_func, t);
fn();
// Alternatively.
_func(t);
}
private:
std::function<void(D*)> _func;
};
I<D> _init_([](D* p) {
p->doIt();
});
int main() {
_init_.run();
}
Instead of std::function<void(D*)> you can also use void(*)(D*) because lambda expression [](D* p) { p->doIt();} doesn't capture anything and hence it is convertible to a plain function pointer void(*)(D*).
The code also doesn't need to allocate D on the heap, an automatic object would suffice. E.g.:
void run() {
T t;
_func(&t);
}
You are trying to magic a D into scopes without it being referenced in intervening scopes, and failing. Not only is the lambda invalid, but so is std::bind(t, _func).
Unrelatedly, you are also leaking the Ds you new.
You can construct a std::function<void (T&)> from a void(T::*)() (member with compatible other arguments)
template<typename T>
class I {
public:
I(std::function<void (T&)> f) : _func(f) {
someManager->register(this);
}
void run() {
T t;
_func(t);
}
private:
std::function<void (T&)> _func;
};
static I<D> _init_(&D::doIt);
You need an instance of D to call doIt, so you must pass it to the lamdba somehow:
#include <functional>
class D {
public:
void doIt() {};
};
template<typename T>
class I {
public:
I(std::function<void (T&)> f) {
//someManager->register(this);
_func = f;
}
void run() {
T* t = new T();
_func(*t);
}
private:
std::function<void (T&)> _func;
};
static I<D> _init_([](D& d) {
d.doIt();
});
This should work, however, note that std::function is quite a beast. It encapsulates all kinds of callables. So when you know that you only need member functions then it might be better to store a member function pointer as member.
And note that your run leaks the newed object. I guess that is just for the example, so I didnt fix it here.
I'm trying to make an interface an abstract class which would be implemented by derivated childs. One of methods in that class has to be variadic (children get one ore more QSharedPointer<QObject> depending on implementation)
The problem is that:
templated methods cannot be virtual
I cannot make a variadic method taking QSharedPointer<QObject>... args arguments because of error: expansion pattern ‘QSharedPointer<QObject>’ contains no argument packs.
Less words, more code:
class BaseClass {
public:
virtual void foo(QSharedPointer<QObject>... args) = 0;
}
class ChildClassA : public BaseClass {
public:
void foo(QSharedPointer<QObject> arg1);
}
class ChildClassB : public BaseClass {
public:
void foo(QSharedPointer<QObject> arg1, QSharedPointer<QObject> arg2);
}
I would like to use above classes to things like that:
template <class T = BaseClass>
class Controller<T>{
void callFoo(QSharedPointer<QObject>... args){
T* = new T();
T->foo(args);
}
}
As you can see the BaseClass is only to say: use one of my children as generic type.
How do I make such things work? Is it even possible in C++?
Since (per the comments) you already have separated the children by arity, and they're managed by separate instantiations of a Controller class template, there is no point in trying to force them all into the same hierarchy -- that only means workarounds and runtime overhead.
Instead, let's make BaseClass a template, and use its parmeter to generate foo's signature.
namespace detail {
template <std::size_t, class T>
using expandHook = T;
}
template <std::size_t N, class = std::make_index_sequence<N>>
struct BaseClass;
template <std::size_t N, std::size_t... Idx>
struct BaseClass<N, std::index_sequence<Idx...>> {
virtual void foo(detail::expandHook<Idx, QSharedPointer<QObject>>... args) = 0;
};
detail::expandHook is kind of a syntactic trick to repeat the QSharedPointer<QObject> type as many times as there are Idxes, which are 0 to N - 1 thanks to the work of std::index_sequence.
Then, children inherit from the corresponding BaseClass:
struct Child : BaseClass<2> {
void foo(QSharedPointer<QObject>, QSharedPointer<QObject>) override;
};
Bonus: a child can inherit from several BaseClass specializations if you want it to support several arities!
Finally, a controller will be parameterized by the adequate BaseClass type, and everything clicks in.
See it live on Coliru (with stubbed types, and main's content would be what's inside a Controller).
If you follow the guideline that public functions should be non-virtual and virtual functions should be private, then you can solve this problem by turning the base function into a variadic template function which delegates to a virtual private function taking a std::vector.
This also has the advantage that all the unpacking happens in one place and derived classes are easier to implement.
Here is an example (I've replaced QSharedPtr with std::shared_ptr and added dummy implementations for QObject so that the example can be compiled without 3rd-party stuff):
#include <memory>
#include <vector>
#include <iostream>
#include <cassert>
struct QObject { virtual void sayHi() const = 0; };
struct DerivedQObject1 : public QObject { void sayHi() const override { std::cout << "1\n"; } };
struct DerivedQObject2 : public QObject { void sayHi() const override { std::cout << "2\n"; } };
class BaseClass {
public:
template <class... Types>
void foo(std::shared_ptr<Types>... args)
{
std::vector<std::shared_ptr<QObject>> vector;
pushBack(vector, args...);
assert(!empty(vector));
doFoo(vector);
}
private:
virtual void doFoo(std::vector<std::shared_ptr<QObject>> const& args) = 0;
template<typename LastType>
static void pushBack(std::vector<std::shared_ptr<QObject>>& vector, LastType arg)
{
vector.push_back(arg);
};
template<typename FirstType, typename ...OtherTypes>
static void pushBack(std::vector<std::shared_ptr<QObject>>& vector, FirstType const& firstArg, OtherTypes... otherArgs)
{
vector.push_back(firstArg);
pushBack(vector, otherArgs...);
};
};
class ChildClassA : public BaseClass {
private:
void doFoo(std::vector<std::shared_ptr<QObject>> const& args) override;
};
void ChildClassA::doFoo(std::vector<std::shared_ptr<QObject>> const& args) {
for (auto const& arg : args) {
arg->sayHi();
}
}
int main() {
ChildClassA child;
auto obj1 = std::make_shared<DerivedQObject1>();
auto obj2 = std::make_shared<DerivedQObject2>();
child.foo(obj1, obj2);
}
Is it somehow possible to store the class from a template without making the the whole class a template?
Task:
I have two functions, v1 without parameters and v2 with parameters,
If v1 was called somewhere nothing happens with Use(), if v2 was called somewhere Use() should execute a function_ptr with the instance I got from DoSometh(T*).
e.g.
class MyClass
{
//v1 no parameters
void DoSomething()
{
}
//v2 with parameter
template<class T>
void DoSomething(T* instance, void (T::*func)())
{
store somewhere?? = instance;
}
void Use()
{
//if DoSometh(T* instance) was used before
if(instance != NULL)
{
(*instance->)//call function pointer from DoSomething(T*,void (T::*)())
}
}
}
std::function problem
update:
class Timer : public ITickable
{
std::function<void()> test; //adding this does weird things
virtual void Tick() {}
}
class MyClass
{
ITickable* tickable_;
void Tick()
{
tickable_->Tick(); //let's assume it points to a Timer obj.
}
}
I think std::function and std::bind (C++11) do accomplish what you want, as already suggested in the comments. A simplified mock-up of your Timer class could be:
class Timer
{
std::function<void()> m_task;
public:
template <typename T>
void setTask(T &instance, void (T::*fcn)()) // consider T const & if applicable
{
m_task = std::bind(fcn, &instance);
}
void fire()
{
if (m_task) // std::function overloads operator bool()
m_task();
}
};
When setTask is called with an object and a member-function that can be called on this object, a std::function object is created (you could choose to do this in a constructor of course). When the timer fires, this object is checked (using operator bool(), provided by std::function), and if it is callable (e.g. when setTask() has been called before), it calls the function.
For example:
class MyClass
{
public:
void func()
{
std::cout << "Hi from MyClass\n";
}
};
class MyOtherClass
{
public:
void func()
{
std::cout << "Hi from MyOtherClass\n";
}
};
int main(int argc, char **argv)
{
MyClass x1;
MyOtherClass x2;
Timer t1, t2;
t1.setTask(x1, &MyClass::func);
t2.setTask(x2, &MyOtherClass::func);
t1.fire();
t2.fire();
}
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.
Not sure how to state subject clearly.
Suppose I have a bunch of functor classes which provide some method. Now I want to create a proxy class which will redirect the method call to one of the underlying functors.
eg:
template<class F>
class proxy_impl : proxy {
F f;
void method() { f.method(); }
};
template<>
class proxy_impl<void> {
virtual void method() = 0;
};
class proxy {
auto_ptr<proxy_impl<void> > *impl_;
template<class F>
proxy(F f) : impl_(new proxy_impl<F>(f)) {}
void method() {
impl->method();
}
};
What is this pattern called and does boost have implementation?
The reason for not having functors inherit directly is because functors can be something like a nameless lambda expression.
Ok, so it seems I need something like boost::any and boost::function functionality in one.
It looks like you're trying to re-invent object-based polymorphism... badly.
here'sow to do what you want
class interface { virtual void method()=0; }
class impl1 : public interface { void method(); }
class impl2 : public interface { void method(); }
...//example usage
interface i *;
if (cond) i = new impl1(); else i= new impl2();
i->method();//calls whichever implementing method was constructed.
Looks a lot like Boost.Function
As you suggest, this can be done with boost.any and boost.function. Specifically:
struct proxy {
template <typename T>
proxy(T t) : obj_(t) {
method = [&obj_] { boost::any_cast<T&>(obj_).method(); }
}
boost::function<void()> method;
private:
boost::any obj_;
};
If .method() is const, then you can do away with the boost::any, and just have the lambda capture the T object by value. In fact, in that case you could just do away with the proxy object and just use a bare boost::function.
I don't think I really understand.. It seems that all you want is to be able to chain functors together:
struct null_functor { void method() { }; };
template <typename F = null_functor>
struct functor1 {
F f;
void method() {
std::cout << "functor1 called!" << std::endl;
f.method();
};
};
template <typename F = null_functor>
struct functor2 {
F f;
void method() {
std::cout << "functor2 called!" << std::endl;
f.method();
};
};
int main() {
functor1 f1;
f1.method();
functor1< functor1 > f11;
f11.method();
functor2< functor1 > f21;
f21.method();
return 0;
};
If you need dynamic binding on top of that, just make one functor be a base class with a virtual method, and derive other functors from it. You could use Boost.Bind as well.