I am trying to achieve the following code pattern.
struct Worker {
void update(/* function pointer */) {
for(unsigned int i = 0; i < 10; i++) {
/* function execution */
}
}
}
template <typename t_derive>
struct BaseCrtp {
void method1() {
static_cast<t_derive*>(this)->method1();
}
void method2() {
static_cast<t_derive*>(this)->worker.update(/*fptr of Derived1::method2*/);
}
}
struct Derived1 : public BaseCrtp<Derived1> {
Worker worker;
void method1() {
std::cout << "Derived1::method1" << std::endl;
}
void method2() {
std::cout << "Derived1::method2" << std::endl;
}
}
I would like to call Derived1's method2 in the instance of Worker::update. How can I define a function pointer that I can inject into the update function.
struct Worker {
void update(/* function pointer */) {
.....
Make Worker::update a template member-function:
struct Worker {
template<typename Func>
void update(Func&& func) {
.....
or use std::function:
struct Worker {
void update(std::function<void()> func) {
.....
Then pass the callback via a lambda in your BaseCrtp<>::method2 as below:
void method2() {
static_cast<t_derive*>(this)->worker.update(
[this]{ static_cast<t_derive*>(this)->method2(); }
);
}
Full example:
#include <iostream>
#include <functional>
struct Worker {
template<typename Func>
void update(Func&& func) {
for(unsigned int i = 0; i < 10; i++) {
func();
}
}
//alternatively....
//
//void update(std::function<void()> func) {
// for(unsigned int i = 0; i < 10; i++) {
// func();
// }
//}
};
template <typename t_derive>
struct BaseCrtp {
void method1() {
static_cast<t_derive*>(this)->method1();
}
void method2() {
static_cast<t_derive*>(this)->worker.update(
[this]{ static_cast<t_derive*>(this)->method2(); }
);
}
};
struct Derived1 : public BaseCrtp<Derived1> {
Worker worker;
void method1() {
std::cout << "Derived1::method1" << std::endl;
}
void method2() {
std::cout << "Derived1::method2" << std::endl;
}
};
template<typename T>
void process(BaseCrtp<T>& t){
t.method2();
}
int main(){
Derived1 d1;
process(d1);
}
As seen here or here (std::function alternative).
As Martin Bonner suggested I think you could make use of Worker template with type template parameter containing Derived class and non-type template parameter with a pointer to the method you would like to invoke. This can be done as follows:
template <class T, void (T::*)(void)>
struct Worker {
void update(T *t) {
t->method2();
}
};
struct Foo {
void method2() { }
Worker<Foo, &Foo::method2> worker;
};
int main() {
Foo foo;
foo.worker.update(&foo);
}
[online demo]
This when using compiler optimization should most probably be inlined now which is actually the point of using crtp in a first place:
[godbolt]
Related
I have created a class Base which has a function addSuccessor() that takes address of function as argument and stores it in successor. How do I pass a function of another object in addSuccessor().
Here is my program. I think my main() has some mistake.
#include <iostream>
#include<vector>
using namespace std;
class Base{
public:
void (*successor)()=NULL;
void addSuccessor ( void (*f)() )
{
successor=f;
}
void start()
{
cout<<"In Class"<<endl;
if(!successor==NULL)
successor();
else
cout<<"No Successor"<<endl;
}
};
class Second{
public:
void foo()
{
cout<<"Successor";
}
};
int main()
{
Base obj;
Second obj2;
obj.addSuccessor(&obj2.foo());
obj.start();
}
Function pointers are very limited. Use a std::function (defined in header <functional>) instead, which can store any invocable object in a type-erased manner, and provide a template member function to set the functor in which perfect forwarding is used to forward the provided functor to successor: (std::forward is defined in header <utility>)
class Base {
std::function<void()> successor;
public:
template <typename F>
void add_successor(F&& f)
{
successor = std::forward<F>(f);
}
void start()
{
if (successor) {
successor();
} else {
std::cout << "No Successor\n";
}
}
};
Then, you can pass a lambda expression to add_successor:
obj.add_successor([&]{ obj2.foo(); });
(live demo)
As a complement to the discussion above (based on #L.F.'s answer):
#include <functional>
#include <iostream>
#include <utility>
class Base {
std::function<int(int)> successor;
public:
template <typename F>
void add_successor(F&& f)
{
successor = std::forward<F>(f);
}
void start()
{
if (successor) {
auto z = std::invoke(successor, 100);
std::cout << "Output = " << z << "\n";
} else {
std::cout << "No Successor\n";
}
}
};
class Second {
public:
int foo(int x)
{
auto y = x + x;
std::cout << "Successor\n";
return y;
}
};
int main()
{
Base obj;
Second obj2;
obj.add_successor([&](int x)->int { return obj2.foo(x); });
obj.start();
}
following this question , I am trying to avoid copy-pasting some code related to calling all of the same-named methods of the mixins of the class BaseSensor.
in sensor.hpp
struct EdgeSensor //a mixin
{
void update(){}
void printStats() {}
};
struct TrendSensor //another mixin
{
void update(){}
void printStats() {}
};
template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
void update() /*{ what goes in here??? }*/
void printStats() /*{ what goes in here??? }*/
};
in sensor.t.hpp
template<typename ... SensorType>
void BaseSensor<SensorType...>::update()
{
int arr[] = { (SensorType::update(), 0)..., 0 };
(void)arr;
}
template<typename ... SensorType>
void BaseSensor<SensorType...>::printStats()
{
int arr[] = { (SensorType::printStats(), 0)..., 0 };
(void)arr;
}
in main.cpp
int main(int , const char **)
{
{
BaseSensor<EdgeSensor,TrendSensor> ets;
ets.update();
ets.printStats();
}
{
BaseSensor<EdgeSensor> ets;
ets.update();
ets.printStats();
}
}
The above code executes the update() of all the mixins in turn, before going on to execute all the printStats() from all the mixins as well.
I wonder if it is somehow possible to avoid duplicating the implementation of BaseSensor::update() and BaseSensor::printStats() and create a generic (template) function that accepts the name of the target function to execute across all the mixins:
For example, I could create a method runAll()
template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
void update() /*{ what goes in here??? }*/
void printStats() /*{ what goes in here??? }*/
template<typename FnName>
void runAll(FnName f)
{
int arr[] = { (SensorType::f(), 0)..., 0 };
(void)arr;
}
};
How would I call it then from BaseSensor::update() and BaseSensor::printStats(). I have attempted to use
void update() { runAll<update>(); }
void printStats() { runAll<printStats>(); }
but this does not work (did not expect it to). The problem with passing function name as a function argument (which I see is many other questions such as here is that I do not know how to point to various ::update() functions from BaseSensor::update(). for example
void update() { runAll<update>( update() ); }
is also not correct.
Is it possible to avoid copying in this case? Can this be done in a one-liner so as to avoid alot of copying using c++11 (i.e. without using generic lambdas as is done here)? How would the template parameters look like if I where to move a working runAll() into file "sensor.t.hpp" ?
Thank you.
As long as the functions to be called are two, you can use a dedicated structure and rely on overloading to solve it.
It follows a minimal, working example:
#include<iostream>
struct Executor {
template<typename T>
static void execute(int, T &t) {
t.update();
}
template<typename T>
static void execute(char, T &t) {
t.printStats();
}
};
struct EdgeSensor
{
void update() { std::cout << "EdgeSensor::update" << std::endl; }
void printStats() { std::cout << "EdgeSensor::printStats" << std::endl; }
};
struct TrendSensor
{
void update() { std::cout << "TrendSensor::update" << std::endl; }
void printStats() { std::cout << "TrendSensor::printStats" << std::endl; }
};
template<typename ... SensorType>
class BaseSensor : public SensorType ...
{
template<typename T>
void execute() {
int arr[] = { (Executor::execute(T{}, static_cast<SensorType&>(*this)), 0)..., 0 };
(void)arr;
}
public:
void update() {
execute<int>();
}
void printStats() {
execute<char>();
}
};
int main() {
BaseSensor<EdgeSensor,TrendSensor> ets;
ets.update();
ets.printStats();
}
In case you have more than two functions to be called, I guess the choice trick applies well here.
You can still write the (simplified version of) generic lambda manually:
void update() {
execute([](auto &t) { t.update(); });
}
becomes so
void update() {
struct {
template <typename T>
void operator () (T& t) const { t.update(); }
} updater;
execute(updater);
}
i'd like to invoke runtime-bound functions of classes, that inherit a binding ability from a common class "Bindable". Is that actually possible?
Here's a stub which surely lacks a lot of template-arguments and namespaces:
#include <iostream> // std::cout
#include <functional> // std::bind
#include <map> // std::map
class Bindable {
public:
void bindFunction (int x, auto newFn) {
mFns.insert(std::pair<int, auto>(x,newFn));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, function> mFns;
};
class A : Bindable {
void funAone (void) {
cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
cout << "called funAtwo" <<std::endl;
}
};
class B : Bindable {
void funBone (void) {
cout << "called funBone" <<std::endl;
}
void funBtwo (void) {
cout << "called funBtwo" <<std::endl;
}
};
int main() {
A a;
B b;
a.bindFunction(1, &A::funAone);
a.bindFunction(2, &A::funAtwo);
b.bindFunction(1, &B::funBone);
b.bindFunction(2, &B::funBtwo);
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
Option #1
Use a CRTP idiom to know what type of pointers to member functions can be stored:
template <typename T>
struct Bindable {
void bindFunction (int x, void(T::*newFn)()) {
mFns.insert(std::make_pair(x,newFn));
}
void invokeFunction (int key) {
(static_cast<T*>(this)->*mFns.at(key))();
}
protected:
std::map<int, void(T::*)()> mFns;
};
struct A : Bindable<A> {
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
DEMO 1
Option #2
Use a type-erasure and make bindFunction a function template:
struct Bindable {
template <typename T, typename std::enable_if<std::is_base_of<Bindable, T>{}, int>::type = 0>
void bindFunction (int x, void(T::*newFn)()) {
mFns.insert(std::make_pair(x, std::bind(newFn, static_cast<T*>(this))));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, std::function<void()>> mFns;
};
struct A : Bindable {
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
DEMO 2
In both cases you can use the code as follows:
int main() {
A a;
B b;
a.bindFunction(1, &A::funAone);
a.bindFunction(2, &A::funAtwo);
b.bindFunction(1, &B::funBone);
b.bindFunction(2, &B::funBtwo);
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
Output:
called funAone
called funAtwo
called funBone
called funBtwo
Yes, it's possible, using std::bind. Note that auto can't be used as a function or template argument.
#include <iostream> // std::cout
#include <functional> // std::bind
#include <map> // std::map
class Bindable {
public:
typedef std::function<void()> Function;
void bindFunction (int x, Function newFn) {
mFns.insert(std::pair<int, Function>(x,newFn));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, Function > mFns;
};
class A : public Bindable {
public:
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
class B : public Bindable {
public:
void funBone (void) {
std::cout << "called funBone" <<std::endl;
}
void funBtwo (void) {
std::cout << "called funBtwo" <<std::endl;
}
};
int main() {
A a;
B b;
a.bindFunction(1, std::bind(&A::funAone, a)); // more than one way to bind
a.bindFunction(2, std::bind(&A::funAtwo, &a)); // the object parameter
b.bindFunction(1, std::bind(&B::funBone, b));
b.bindFunction(2, std::bind(&B::funBtwo, &b));
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
This is what I would like to do using templates:
struct op1
{
virtual void Method1() = 0;
}
...
struct opN
{
virtual void MethodN() = 0;
}
struct test : op1, op2, op3, op4
{
virtual void Method1(){/*do work1*/};
virtual void Method2(){/*do work2*/};
virtual void Method3(){/*do work3*/};
virtual void Method4(){/*do work4*/};
}
I would like to have a class that simply derives from a template class that provides these method declarations while at the same time making them virtual. This is what I've managed to come up with:
#include <iostream>
template< size_t N >
struct ops : ops< N - 1 >
{
protected:
virtual void DoStuff(){ std::cout<<N<<std::endl; };
public:
template< size_t i >
void Method()
{ if( i < N ) ops<i>::DoStuff(); }
//leaving out compile time asserts for brevity
};
template<>
struct ops<0>
{
};
struct test : ops<6>
{
};
int main( int argc, char ** argv )
{
test obj;
obj.Method<3>(); //prints 3
return 0;
}
However, as you've probably guessed, I am unable to override any of the 6 methods I have inherited. I'm obviously missing something here. What is my error? No, this isn't homework. This is curiosity.
Tested with GCC 4.3. Don't even know why I spent time on this :-/
#include <iostream>
template <std::size_t N>
struct mark
{ };
template <std::size_t N>
struct op : op <N - 1>
{
virtual void do_method (const mark <N>&) = 0;
};
template <>
struct op <1>
{
virtual void do_method (const mark <1>&) = 0;
};
struct test : op <2>
{
template <std::size_t K>
void
method ()
{ do_method (mark <K> ()); }
virtual void do_method (const mark <1>&)
{ std::cout << "1\n"; }
virtual void do_method (const mark <2>&)
{ std::cout << "2\n"; }
};
int
main ()
{
test x;
x.method <1> ();
x.method <2> ();
}
I don't know how to move the "prettifier" method() template function out of test.
template< size_t N >
struct ops : ops< N - 1 >
This codes an endless loop. The recursion doesn't stop when N reaches 0. Add a specialization for the end case, immediately after the primary template:
template<>
struct ops<0> {}
Also, what does this do? Why not just call ops<i>::DoStuff() directly?
template< size_t i >
void Method()
{ if( i < N ) ops<i>::DoStuff(); }
To mimic your original desire:
#define MAKE_OPS(N) template<> struct Ops<N> : Ops<N-1> { virtual void Method##N() = 0; }
template<int N>
struct Ops;
template<>
struct Ops<0> { };
MAKE_OPS(1);
MAKE_OPS(2);
template<> struct Ops<3> : Ops<2> { virtual void Method3() { std::cout << "3" << std::endl; } };
MAKE_OPS(4);
MAKE_OPS(5);
MAKE_OPS(6);
struct Test : Ops<3> {
virtual void Method1() { std::cout << 1 << std::endl; }
virtual void Method2() { std::cout << 2 << std::endl; }
};
Following code does NOT work, but it expresses well what I wish to do. There is a problem with the template struct container, which I think SHOULD work because it's size is known for any template argument.
class callback {
public:
// constructs a callback to a method in the context of a given object
template<class C>
callback(C& object, void (C::*method)())
: ptr.o(object), ptr.m(method) {}
// calls the method
void operator()() {
(&ptr.o ->* ptr.m) ();
}
private:
// container for the pointer to method
template<class C>
struct {
C& o;
void (C::*m)();
} ptr;
};
Is there any way to do such a thing? I mean have a non-template class callback which wraps any pointer to method?
Thanks C++ gurus!
Edit:
Please see this:
Callback in C++, template member? (2)
This is a complete working example that does what I think you're trying to do:
#include <iostream>
#include <memory>
// INTERNAL CLASSES
class CallbackSpecBase
{
public:
virtual ~CallbackSpecBase() {}
virtual void operator()() const = 0;
};
template<class C>
class CallbackSpec : public CallbackSpecBase
{
public:
CallbackSpec(C& o, void (C::*m)()) : obj(o), method(m) {}
void operator()() const { (&obj->*method)(); }
private:
C& obj;
void (C::*method)();
};
// PUBLIC API
class Callback
{
public:
Callback() {}
void operator()() { (*spec)(); }
template<class C>
void set(C& o, void (C::*m)()) { spec.reset(new CallbackSpec<C>(o, m)); }
private:
std::auto_ptr<CallbackSpecBase> spec;
};
// TEST CODE
class Test
{
public:
void foo() { std::cout << "Working" << std::endl; }
void bar() { std::cout << "Like a charm" << std::endl; }
};
int main()
{
Test t;
Callback c;
c.set(t, &Test::foo);
c();
c.set(t, &Test::bar);
c();
}
I recently implemented this:
#define UNKOWN_ITEM 0xFFFFFFFF
template <typename TArg>
class DelegateI
{
public:
virtual void operator()(TArg& a)=0;
virtual bool equals(DelegateI<TArg>* d)=0;
};
template <class TArg>
class Event
{
public:
Event()
{
}
~Event()
{
for (size_t x=0; x<m_vDelegates.size(); x++)
delete m_vDelegates[x];
}
void operator()(TArg& a)
{
for (size_t x=0; x<m_vDelegates.size(); x++)
{
m_vDelegates[x]->operator()(a);
}
}
void operator+=(DelegateI<TArg>* d)
{
if (findInfo(d) != UNKOWN_ITEM)
{
delete d;
return;
}
m_vDelegates.push_back(d);
}
void operator-=(DelegateI<TArg>* d)
{
uint32 index = findInfo(d);
delete d;
if (index == UNKOWN_ITEM)
return;
m_vDelegates.erase(m_vDelegates.begin()+index);
}
protected:
int findInfo(DelegateI<TArg>* d)
{
for (size_t x=0; x<m_vDelegates.size(); x++)
{
if (m_vDelegates[x]->equals(d))
return (int)x;
}
return UNKOWN_ITEM;
}
private:
std::vector<DelegateI<TArg>*> m_vDelegates;
};
template <class TObj, typename TArg>
class ObjDelegate : public DelegateI<TArg>
{
public:
typedef void (TObj::*TFunct)(TArg&);
ObjDelegate(TObj* t, TFunct f)
{
m_pObj = t;
m_pFunct = f;
}
virtual bool equals(DelegateI<TArg>* di)
{
ObjDelegate<TObj,TArg> *d = dynamic_cast<ObjDelegate<TObj,TArg>*>(di);
if (!d)
return false;
return ((m_pObj == d->m_pObj) && (m_pFunct == d->m_pFunct));
}
virtual void operator()(TArg& a)
{
if (m_pObj && m_pFunct)
{
(*m_pObj.*m_pFunct)(a);
}
}
TFunct m_pFunct; // pointer to member function
TObj* m_pObj; // pointer to object
};
template <typename TArg>
class FunctDelegate : public DelegateI<TArg>
{
public:
typedef void (*TFunct)(TArg&);
FunctDelegate(TFunct f)
{
m_pFunct = f;
}
virtual bool equals(DelegateI<TArg>* di)
{
FunctDelegate<TArg> *d = dynamic_cast<FunctDelegate<TArg>*>(di);
if (!d)
return false;
return (m_pFunct == d->m_pFunct);
}
virtual void operator()(TArg& a)
{
if (m_pFunct)
{
(*m_pFunct)(a);
}
}
TFunct m_pFunct; // pointer to member function
};
template <typename TArg>
class ProxieDelegate : public DelegateI<TArg>
{
public:
ProxieDelegate(Event<TArg>* e)
{
m_pEvent = e;
}
virtual bool equals(DelegateI<TArg>* di)
{
ProxieDelegate<TArg> *d = dynamic_cast<ProxieDelegate<TArg>*>(di);
if (!d)
return false;
return (m_pEvent == d->m_pEvent);
}
virtual void operator()(TArg& a)
{
if (m_pEvent)
{
(*m_pEvent)(a);
}
}
Event<TArg>* m_pEvent; // pointer to member function
};
template <class TObj, class TArg>
DelegateI<TArg>* delegate(TObj* pObj, void (TObj::*NotifyMethod)(TArg&))
{
return new ObjDelegate<TObj, TArg>(pObj, NotifyMethod);
}
template <class TArg>
DelegateI<TArg>* delegate(void (*NotifyMethod)(TArg&))
{
return new FunctDelegate<TArg>(NotifyMethod);
}
template <class TArg>
DelegateI<TArg>* delegate(Event<TArg>* e)
{
return new ProxieDelegate<TArg>(e);
}
use it like so:
define:
Event<SomeClass> someEvent;
enlist callbacks:
someEvent += delegate(&someFunction);
someEvent += delegate(classPtr, &class::classFunction);
someEvent += delegate(&someOtherEvent);
trigger:
someEvent(someClassObj);
You can also make your own delegates and overide what they do. I made a couple of others with one being able to make sure the event triggers the function in the gui thread instead of the thread it was called.
You need to use polymorphism. Use an abstract base class with a virtual invocation method (operator() if you please), with a templated descendant that implements the virtual method using the correct type signature.
The way you have it now, the data holding the type is templated, but the code meant to invoke the method and pass the object isn't. That won't work; the template type parameters need to flow through both construction and invocation.
#Barry Kelly
#include <iostream>
class callback {
public:
virtual void operator()() {};
};
template<class C>
class callback_specialization : public callback {
public:
callback_specialization(C& object, void (C::*method)())
: o(object), m(method) {}
void operator()() {
(&o ->* m) ();
}
private:
C& o;
void (C::*m)();
};
class X {
public:
void y() { std::cout << "ok\n"; }
};
int main() {
X x;
callback c(callback_specialization<X>(x, &X::y));
c();
return 0;
}
I tried this, but it does not work (print "ok")... why?
Edit:
As Neil Butterworth mentioned, polymorphism works through pointers and references,
X x;
callback& c = callback_specialization<X>(x, &X::y);
c();
Edit:
With this code, I get an error:
invalid initialization of non-const reference of type ‘callback&’
from a temporary of type ‘callback_specialization<X>’
Now, I don't understand that error, but if I replace callback& c with const callback& c and virtual void operator()() with virtual void operator()() const, it works.
You didn't say what errors you found, but I found that this worked:
template<typename C>
class callback {
public:
// constructs a callback to a method in the context of a given object
callback(C& object, void (C::*method)())
: ptr(object,method) {}
// calls the method
void operator()() {
(&ptr.o ->* ptr.m) ();
}
private:
// container for the pointer to method
// template<class C>
struct Ptr{
Ptr(C& object, void (C::*method)()): o(object), m(method) {}
C& o;
void (C::*m)();
} ptr;
};
Note that Ptr needs a constructor as it has a reference member.
You could do without struct Ptr and have the raw members.
Tested with VS2008 express.
Improving the OP's answer:
int main() {
X x;
callback_specialization<X> c(x, &X::y);
callback& ref(c);
c();
return 0;
}
This prints "ok".
Tested on VS2008 express.
Please see this
Callback in C++, template member? (2)