I need to solve such a problem.
There is a base class and two inherited classes. The base class contains method which needs a function-pointer as a parameter. But such functions are defined in inherited classes.
class CBase;
typedef bool (CBase::*FPredicate)();
class CBase
{
public:
CBase() {}
~CBase() {}
protected:
//this method waits until 'predicate' is true or until 'timeout' ms. passed
//and returns true if 'predicate' is true eventually
bool WaitEvent(FPredicate predicate, int timeout)
{
bool result = false;
int time1 = GetTickCount();
int time2;
bool isEnd = false;
while(!isEnd)
{
result = isEnd = (this->*predicate)();
time2 = GetTickCount();
if(time2 - time1 > timeout && !isEnd)
isEnd = true;
}
return result;
}
};
class CChildA : public CBase
{
protected:
bool a1() {/*some work*/}
bool a2() {/*some work*/}
void a_main()
{
...
WaitEvent(&CChildA::a1, 100);
...
WaitEvent(&CChildA::a2, 100);
...
}
};
class CChildB : public CBase
{
protected:
bool b1() {/*some work*/}
bool b2() {/*some work*/}
void b_main()
{
...
WaitEvent(&CChildB::b1, 100);
...
WaitEvent(&CChildB::b2, 100);
...
}
};
MSVC 2005 compiler gives an error on WaitEvent calls:
error C2664: 'CBase::WaitEvent' : cannot convert parameter 1 from 'bool (__thiscall CChildA::* )(void)' to 'FPredicate'
A question is: how shall I change the code to make it work? will it be safe to rewrite WaitEvent call as
WaitEvent((FPredicate)(&CChildA::a1), 100)?
In this case compiler tells of no error but is it safe? Or is there a better way of solving a problem?
Thank you in advance.
The problem is that the implicitly passed this differs in type. Either you cast it, but that will probably fail in the presence of multiple inheritance. A better & more robust solution would be to change the signature to:
template< typename T >
bool WaitEvent( bool ( T::*predicate )(), int timeout ) { ... }
You can do it using a template class to do a closure of your child object and its function member saving it's correct type. And then using virtual functions to let the base class calls it through usual polymorphism.
A similar mechanism is used in shared_ptr to call destructors. See: http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-1-of-n
#include <iostream>
struct CPredicateBase
{
virtual ~CPredicateBase() {}
virtual bool operator()() = 0;
};
template <class T>
struct CPredicate : public CPredicateBase
{
bool (T::*func)();
T* self;
CPredicate(T* self_, bool (T::*func_)())
: func(func_), self(self_) {}
bool operator() () { return (self->*func)(); }
};
class CBase
{
public:
bool WaitEvent(CPredicateBase& predicate, int imeout)
{
/// just to show the call
bool b = predicate();
std::cout << "WaitEvent called predicate() => " << b << std::endl;
return b;
}
};
class CChildA : public CBase
{
public:
bool a1() { return false; }
bool a2() { return true; }
void a_main()
{
std::cout << "CChildA::a_main()" << std::endl;
CPredicate<CChildA> caller1(this, &CChildA::a1);
bool ra1 = WaitEvent(caller1, 100);
CPredicate<CChildA> caller2(this, &CChildA::a2);
bool ra2 = WaitEvent(caller2, 100);
}
};
class CChildB : public CBase
{
public:
bool b1() { return false; }
bool b2() { return true; }
void b_main()
{
std::cout << "CChildB::b_main()" << std::endl;
CPredicate<CChildB> caller1(this, &CChildB::b1);
bool rb1 = WaitEvent(caller1, 100);
CPredicate<CChildB> caller2(this, &CChildB::b2);
bool rb2 = WaitEvent(caller2, 100);
}
};
int main(int argc, char const* argv[])
{
CChildA cA;
CChildB cB;
cA.a_main();
cB.b_main();
return 0;
}
Related
I am trying to create a pattern where an abstract class has several methods where all get the same member. The derived implementation is on a specific member type and the pattern should redundant the need to downcast the types.
The following is not working:
Assume these type classes
//--------------
// Data classes
//--------------
class TypeA
{
virtual int a() = 0;
};
class TypeB : public TypeA
{
int a() override
{
return 5;
}
};
Pattern:
//-------------------
// Base action class.
//-------------------
class ExampleBase
{
public:
virtual bool f1(TypeA& val) = 0;
virtual bool f2(TypeA& val) = 0;
};
//----------------------------------
// Base specific Typed action class.
//----------------------------------
template<class T>
class ExampleSpecific1 : public ExampleBase
{
public:
virtual bool specificF1(T& specificVal) = 0;
virtual bool specificF2(T& specificVal) = 0;
bool f1(TypeA& val) override
{
return fRunner<bool, specificF1>(val, false);
}
bool f2(TypeA& val) override
{
return fRunner<bool, specificF2>(val, false);
}
private:
// Run the specific function with the specific type
template<class S, S (*pf)(T& val)>
S fRunner(TypeA& val, S defaultValue)
{
S ret = defaultValue;
T& specificVal = dynamic_cast<T&>(val);
if (&specificVal != nullptr) {
ret = pf(specificVal);
}
return ret;
}
};
The implementation
//----------------------
// Class Implementation.
//----------------------
class ExampleImpl : public ExampleSpecific1<TypeB>
{
public:
bool specificF1(TypeB& specificVal) override
{
// Do something
}
bool specificF2(TypeB& specificVal) override
{
// Do something
}
};
Usage:
//-----------
// Class Use.
//-----------
void main()
{
ExampleImpl impl;
TypeB myVal;
TypeA& myBaseVal = myVal;
impl.f1(myBaseVal);
impl.f2(myBaseVal);
}
I get the following compilation error:
error C2672: 'ExampleSpecific1<TypeB>::fRunner': no matching overloaded function found
note: while compiling class template member function 'bool ExampleSpecific1<TypeB>::f2(TypeA &)'
note: see reference to function template instantiation 'bool ExampleSpecific1<TypeB>::f2(TypeA &)' being compiled
note: see reference to class template instantiation 'ExampleSpecific1<TypeB>' being compiled
error C2975: 'pf': invalid template argument for 'ExampleSpecific1<TypeB>::fRunner', expected compile-time constant expression
note: see declaration of 'pf'
A function template that does work (when the function is not inside a class):
Based on the previous example:
template<class T, bool (*pf1)(T& Val), bool (*pf2)(T& Val)>
class ExampleSpecific2 : public ExampleBase
{
public:
bool f1(TypeA& val) override
{
bool ret = false;
T& specificVal = dynamic_cast<T&>(val);
if (&specificVal != nullptr) {
ret = pf1(specificVal);
}
return ret;
}
bool f2(TypeA& val) override
{
bool ret = false;
T& specificVal = dynamic_cast< T&>(val);
if (&specificVal != nullptr) {
ret = pf2(specificVal);
}
return ret;
}
};
External functions:
bool extF1(TypeB& val)
{
// Do something.
}
bool extF2(TypeB& val)
{
// Do something.
}
Useage:
//-----------
// Class Use.
//-----------
void main()
{
TypeB myVal;
TypeA& myBaseVal = myVal;
ExampleSpecific2<TypeB, extF1, extF2> impl2;
impl2.f1(myBaseVal);
impl2.f2(myBaseVal);
}
In the example that does not work, I can implement the down cast in each of the implementation and then it works, but it is ugly and is not generic. In the working example I want the function to be in the internal implementation of the class and not external to it, this is important in more complicated scenarios, where the base class is calling several of the derived methods.
BTW I don't like this post Title, if you have a better suggestion that I like, this will be great.
Note :
main should return an int, not void
if (&specificVal != nullptr) will be always true, reference cannot be null.
I am not sur why you got this error message, with gcc I got :
no matching member function for call to 'fRunner'
Because pf type was bool (ExampleSpecific1<TypeB>::*)(TypeB &) which didn't match with S (*pf)(T& val). The first one need an class object.
So I just use the C++17 auto :
template<class S, auto pf>
S fRunner(TypeA& val, S defaultValue){...}
But you can use the full type if you want.
Next We need to call the member function. I don't like (nor remember) the member function call syntaxe, so I just use std::invoke of C++17. (see : https://en.cppreference.com/w/cpp/utility/functional/invoke)
Live : https://wandbox.org/permlink/rEqgLSwSjEfqRK2o
#include <iostream>
#include <vector>
//--------------
// Data classes
//--------------
class TypeA
{
virtual int a() = 0;
};
class TypeB : public TypeA
{
int a() override
{
return 5;
}
};
//-------------------
// Base action class.
//-------------------
class ExampleBase
{
public:
virtual bool f1(TypeA& val) = 0;
virtual bool f2(TypeA& val) = 0;
};
//----------------------------------
// Base specific Typed action class.
//----------------------------------
template<class T>
class ExampleSpecific1 : public ExampleBase
{
private:
// Run the specific function with the specific type
template<class S, auto pf>
S fRunner(TypeA& val, S defaultValue)
{
S ret = defaultValue;
T& specificVal = dynamic_cast<T&>(val);
ret = std::invoke(pf, *this, specificVal);
return ret;
}
public:
virtual bool specificF1(T& specificVal) = 0;
virtual bool specificF2(T& specificVal) = 0;
bool f1(TypeA& val) override
{
return this->fRunner<bool, &ExampleSpecific1<T>::specificF1>(val, false);
}
bool f2(TypeA& val) override
{
return this->fRunner<bool, &ExampleSpecific1<T>::specificF2>(val, false);
}
};
// Class Implementation.
//----------------------
class ExampleImpl : public ExampleSpecific1<TypeB>
{
public:
bool specificF1(TypeB& ) override
{
std::cout << "specificF1" << std::endl;
return true;
}
bool specificF2(TypeB& ) override
{
std::cout << "specificF2" << std::endl;
return true;
}
};
//-----------
// Class Use.
//-----------
int main()
{
ExampleImpl impl;
TypeB myVal;
TypeA& myBaseVal = myVal;
impl.f1(myBaseVal);
impl.f2(myBaseVal);
}
Pre C++17 : https://wandbox.org/permlink/HSGMy4zb4TgusESf
template<class S, S (ExampleSpecific1<T>::*pf)(T &)> // full type since auto is C++ 17
S fRunner(TypeA& val, S defaultValue)
{
S ret = defaultValue;
T& specificVal = dynamic_cast<T&>(val);
ret = (this->*pf)(specificVal); // Ugly pre 17
return ret;
}
I am currently working on a small private project using C++ i came up with the following structure:
#include <iostream>
class A
{
std::vector<int> vec;
protected:
virtual bool onAdd(int toAdd) {
// should the 'adding' be suppressed?
// do some A specific checks
std::cout << "A::onAdd()" << std::endl;
return false;
}
public:
void add(int i) {
if(!onAdd(i)) {
// actual logic
vec.push_back(i);
}
}
};
class B : public A
{
protected:
bool onAdd(int toAdd) override {
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return false;
}
};
In this example onAdd is basically meant to be a callback for add, but in a more polymorphic way.
The actual problem arises when a class C inherits from B and wants to override onAdd too. In this case the implementation in B will get discarded (i.e. not called) when calling C::add. So basically what I would like to achieve is a constructor-like behaviour where I am able to override the same method in different positions in the class hierarchy and all of those getting called.
My question now is: Is there a possibility/design to achieve this? I am sure that it wouldn't be as easy as cascading constructors, though.
Note: Don't focus too much on the add example. The question is about the callback like structure and not if it makes sense with an add.
I would just call my parents onAdd()
bool C::onAdd(int toAdd) {return my_answer && B::onAdd(toAdd);}
This can be a little confusing if you're expecting other developers to inherit from your base class. But for small private hierarchies it works perfectly.
I sometimes include a using statement to make this more explicit
class C : public B
{
using parent=B;
bool onAdd(int toAdd) override {return my_answer && parent::onAdd(toAdd);}
};
struct RunAndDiscard {
template<class Sig, class...Args>
void operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return;
for (auto* i = start; i != (finish-1); ++i) {
(*i)(args...);
}
(*(finish-1))(std::forward<Args>(args)...);
}
};
template<class Sig, class Combine=RunAndDiscard>
struct invokers {
std::vector<Sig*> targets;
template<class...Args>
decltype(auto) operator()(Args&&...args)const {
return Combine{}( targets.data(), targets.data()+targets.size(), std::forward<Args>(args)... );
}
};
struct AndTogetherResultWithShortCircuit {
template<class Sig, class...Args>
bool operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return true;
for (auto* i = start; i != (finish-1); ++i) {
if (!(*i)(args...)) return false;
}
return (*(finish-1))(std::forward<Args>(args)...);
}
};
This creates a per-instance table of things to do onAdd.
Creating a per-class table is harder; you need to chain your table with your parent type's table, which requires per-class boilerplate.
There is no way to get the C++ compiler to write either the per-instance version, or the per-class version, without doing it yourself.
There are C++20 proposals involving reflection and reification, plus the metaclass proposal, which may involve automating writing code like this (on both a per-instance and per-class basis).
Here is a live example of this technique being tested:
struct AndTogetherResultWithShortCircuit {
template<class Sig, class...Args>
bool operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return true;
for (auto* i = start; i != (finish-1); ++i) {
if (!(*i)(args...)) return false;
}
return (*(finish-1))(std::forward<Args>(args)...);
}
};
class A {
std::vector<int> vec;
protected:
invokers<bool(A*, int), AndTogetherResultWithShortCircuit> onAdd;
public:
void add(int i) {
if (!onAdd(this, i)) {
vec.push_back(i);
}
}
};
class B : public A
{
public:
B() {
onAdd.targets.push_back([](A* self, int x)->bool{
// do some B specific checks
std::cout << "B::onAdd(" << x << ")" << std::endl;
return x%2;
});
}
};
class C : public B
{
public:
C() {
onAdd.targets.push_back([](A* self, int x)->bool{
// do some B specific checks
std::cout << "C::onAdd(" << x << ")" << std::endl;
return false;
});
}
};
When you want to write your own OO-system, you can in C++, but C++ doesn't write it for you.
If you want a generic solution perhaps you could use CRTP with variadic templates instead of runtime polymophism.
Taking inspiration from this answer and this answer:
template<class... OnAdders> class A : private OnAdders... {
std::vector<int> vec;
template<class OnAdder>
bool onAdd(int toAdd){
return static_cast<OnAdder*>(this)->onAdd(toAdd);
}
template<typename FirstOnAdder, typename SecondOnAdder, class... RestOnAdders>
bool onAdd(int toAdd){
if (onAdd<FirstOnAdder>(toAdd))
return true;
return onAdd<SecondOnAdder, RestOnAdders...>(toAdd);
}
public:
void add(int i) {
if (onAdd<OnAdders...>(i))
return;
// actual logic
vec.push_back(i);
}
};
class B {
public:
bool onAdd(int toAdd) {
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return false;
}
};
Which you could use like:
A<B,C> a;
a.add(42);
Live demo.
The following solution uses std::function to add each callback during each constructor:
#include <iostream>
#include <vector>
#include <functional>
class A
{
std::vector<int> vec;
protected:
bool onAdd(int toAdd)
{
// do some A specific checks
std::cout << "A::onAdd()" << std::endl;
return true;
}
// vector of callback functions. Initialized with A::onAdd() callback as the first entry
std::vector<std::function<bool(int)>> callbacks{{[this](int toAdd){return onAdd(toAdd); }}};
public:
void add(int i)
{
for(auto& callback : callbacks) {
if(!callback(i))
return;
}
// actual logic
vec.push_back(i);
}
};
class B : public A
{
public:
B()
{
callbacks.emplace_back([this](int toAdd){return onAdd(toAdd); });
}
protected:
bool onAdd(int toAdd)
{
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return true;
}
};
class C : public B
{
public:
C()
{
callbacks.emplace_back([this](int toAdd){return onAdd(toAdd); });
}
protected:
bool onAdd(int toAdd)
{
// do some C specific checks
std::cout << "C::onAdd()" << std::endl;
// must also call B::onAdd()
return true;
}
};
int main()
{
C c;
c.add(5);
}
Prints:
A::onAdd()
B::onAdd()
C::onAdd()
I would like to do something like this:
class Base{};
class Specialized1 : public Base
{
public:
int GetCount(){ return 1; }
};
class Specialized2 : public Base
{
public:
bool IsCorrect() { return true; }
};
class Example
{
public:
template< class ATTR_CLASS, class RETURNED_PARAMETER_CLASS >
int GetPerfectAttributeIndex( const RETURNED_PARAMETER_CLASS & perfect_parameter, ***RETURNED_PARAMETER_CLASS (*function_to_call)()*** )
{
for ( int i = 0; i < AttributeCount; ++i )
{
if ( perfect_parameter ==
static_cast< ATTR_CLASS >( MyAttributeTable[ i ] )->function_to_call() )
{
return i;
}
}
return -1;
}
Base** MyAttributeTable;
int AttributeCount;
};
And the call would be:
example.GetPerfectAttributeIndex< Specialized1, int >( 1, &Specialized1::GetCount );
So I know that this code is not working because of the part between ***
But how can I change it to make it work? Using some C++11 magic?
Thank you for any help!
The problem is that function_to_call is not a pointer to member function. You should also downcast from Base* more safe with dynamic_cast and checking against nullptr afterwards.
class Base
{
public:
virtual ~Base() = default;
};
class Specialized1 : public Base
{
public:
int GetCount() { return 1; }
};
class Specialized2 : public Base
{
public:
bool IsCorrect() { return true; }
};
class Example
{
public:
template <class ATTR_CLASS, class RETURNED_PARAMETER_CLASS>
int GetPerfectAttributeIndex(
RETURNED_PARAMETER_CLASS const& perfect_parameter,
RETURNED_PARAMETER_CLASS(ATTR_CLASS::*function_to_call)()) // added ATTR_CLASS::
{
for(int i = 0; i < AttributeCount; ++i)
{
auto ptr = dynamic_cast<ATTR_CLASS*>(MyAttributeTable[i]);
if(!ptr)
{
// handle the case of an invalid cast
}
if(perfect_parameter == (ptr->*function_to_call)()) // extra parentheses added and ->* operator used
return i;
}
return -1;
}
Base** MyAttributeTable;
int AttributeCount;
};
I realize that I'll most likely get a lot of "you shouldn't do that because..." answers and they are most welcome and I'll probably totally agree with your reasoning, but I'm curious as to whether this is possible (as I envision it).
Is it possible to define a type of dynamic/generic object in C++ where I can dynamically create properties that are stored and retrieved in a key/value type of system? Example:
MyType myObject;
std::string myStr("string1");
myObject.somethingIJustMadeUp = myStr;
Note that obviously, somethingIJustMadeUp is not actually a defined member of MyType but it would be defined dynamically. Then later I could do something like:
if(myObject.somethingIJustMadeUp != NULL);
or
if(myObject["somethingIJustMadeUp"]);
Believe me, I realize just how terrible this is, but I'm still curious as to whether it's possible and if it can be done in a way that minimizes it's terrible-ness.
C++Script is what you want!
Example:
#include <cppscript>
var script_main(var args)
{
var x = object();
x["abc"] = 10;
writeln(x["abc"]);
return 0;
}
and it's a valid C++.
You can do something very similar with std::map:
std::map<std::string, std::string> myObject;
myObject["somethingIJustMadeUp"] = myStr;
Now if you want generic value types, then you can use boost::any as:
std::map<std::string, boost::any> myObject;
myObject["somethingIJustMadeUp"] = myStr;
And you can also check if a value exists or not:
if(myObject.find ("somethingIJustMadeUp") != myObject.end())
std::cout << "Exists" << std::endl;
If you use boost::any, then you can know the actual type of value it holds, by calling .type() as:
if (myObject.find("Xyz") != myObject.end())
{
if(myObject["Xyz"].type() == typeid(std::string))
{
std::string value = boost::any_cast<std::string>(myObject["Xyz"]);
std::cout <<"Stored value is string = " << value << std::endl;
}
}
This also shows how you can use boost::any_cast to get the value stored in object of boost::any type.
This can be a solution, using RTTI polymorphism
#include <map>
#include <memory>
#include <iostream>
#include <stdexcept>
namespace dynamic
{
template<class T, class E>
T& enforce(T& z, const E& e)
{ if(!z) throw e; return z; }
template<class T, class E>
const T& enforce(const T& z, const E& e)
{ if(!z) throw e; return z; }
template<class Derived>
class interface;
class aggregate;
//polymorphic uncopyable unmovable
class property
{
public:
property() :pagg() {}
property(const property&) =delete;
property& operator=(const property&) =delete;
virtual ~property() {} //just make it polymorphic
template<class Interface>
operator Interface*() const
{
if(!pagg) return 0;
return *pagg; //let the aggregate do the magic!
}
aggregate* get_aggregate() const { return pagg; }
private:
template<class Derived>
friend class interface;
friend class aggregate;
static unsigned gen_id()
{
static unsigned x=0;
return enforce(++x,std::overflow_error("too many ids"));
}
template<class T>
static unsigned id_of()
{ static unsigned z = gen_id(); return z; }
aggregate* pagg;
};
template<class Derived>
class interface: public property
{
public:
interface() {}
virtual ~interface() {}
unsigned id() const { return property::id_of<Derived>(); }
};
//sealed movable
class aggregate
{
public:
aggregate() {}
aggregate(const aggregate&) = delete;
aggregate& operator=(const aggregate&) = delete;
aggregate(aggregate&& s) :m(std::move(s.m)) {}
aggregate& operator=(aggregate&& s)
{ if(this!=&s) { m.clear(); std::swap(m, s.m); } return *this; }
template<class Interface>
aggregate& add_interface(interface<Interface>* pi)
{
m[pi->id()] = std::unique_ptr<property>(pi);
static_cast<property*>(pi)->pagg = this;
return *this;
}
template<class Inteface>
aggregate& remove_interface()
{ m.erase[property::id_of<Inteface>()]; return *this; }
void clear() { m.clear(); }
bool empty() const { return m.empty(); }
explicit operator bool() const { return empty(); }
template<class Interface>
operator Interface*() const
{
auto i = m.find(property::id_of<Interface>());
if(i==m.end()) return nullptr;
return dynamic_cast<Interface*>(i->second.get());
}
template<class Interface>
friend aggregate& operator<<(aggregate& s, interface<Interface>* pi)
{ return s.add_interface(pi); }
private:
typedef std::map<unsigned, std::unique_ptr<property> > map_t;
map_t m;
};
}
/// this is a sample on how it can workout
class interface_A: public dynamic::interface<interface_A>
{
public:
virtual void methodA1() =0;
virtual void methodA2() =0;
};
class impl_A1: public interface_A
{
public:
impl_A1() { std::cout<<"creating impl_A1["<<this<<"]"<<std::endl; }
virtual ~impl_A1() { std::cout<<"deleting impl_A1["<<this<<"]"<<std::endl; }
virtual void methodA1() { std::cout<<"interface_A["<<this<<"]::methodA1 on impl_A1 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodA2() { std::cout<<"interface_A["<<this<<"]::methodA2 on impl_A1 in aggregate "<<get_aggregate()<<std::endl; }
};
class impl_A2: public interface_A
{
public:
impl_A2() { std::cout<<"creating impl_A2["<<this<<"]"<<std::endl; }
virtual ~impl_A2() { std::cout<<"deleting impl_A2["<<this<<"]"<<std::endl; }
virtual void methodA1() { std::cout<<"interface_A["<<this<<"]::methodA1 on impl_A2 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodA2() { std::cout<<"interface_A["<<this<<"]::methodA2 on impl_A2 in aggregate "<<get_aggregate()<<std::endl; }
};
class interface_B: public dynamic::interface<interface_B>
{
public:
virtual void methodB1() =0;
virtual void methodB2() =0;
};
class impl_B1: public interface_B
{
public:
impl_B1() { std::cout<<"creating impl_B1["<<this<<"]"<<std::endl; }
virtual ~impl_B1() { std::cout<<"deleting impl_B1["<<this<<"]"<<std::endl; }
virtual void methodB1() { std::cout<<"interface_B["<<this<<"]::methodB1 on impl_B1 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodB2() { std::cout<<"interface_B["<<this<<"]::methodB2 on impl_B1 in aggregate "<<get_aggregate()<<std::endl; }
};
class impl_B2: public interface_B
{
public:
impl_B2() { std::cout<<"creating impl_B2["<<this<<"]"<<std::endl; }
virtual ~impl_B2() { std::cout<<"deleting impl_B2["<<this<<"]"<<std::endl; }
virtual void methodB1() { std::cout<<"interface_B["<<this<<"]::methodB1 on impl_B2 in aggregate "<<get_aggregate()<<std::endl; }
virtual void methodB2() { std::cout<<"interface_B["<<this<<"]::methodB2 on impl_B2 in aggregate "<<get_aggregate()<<std::endl; }
};
int main()
{
dynamic::aggregate agg1;
agg1 << new impl_A1 << new impl_B1;
dynamic::aggregate agg2;
agg2 << new impl_A2 << new impl_B2;
interface_A* pa = 0;
interface_B* pb = 0;
pa = agg1; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
agg2 = std::move(agg1);
pa = agg2; if(pa) { pa->methodA1(); pa->methodA2(); }
pb = *pa; if(pb) { pb->methodB1(); pb->methodB2(); }
return 0;
}
tested with MINGW4.6 on WinXPsp3
Yes it is terrible. :D
It had been done numerous times to different extents and success levels.
QT has Qobject from which everything related to them decends.
MFC has CObject from which eveything decends as does C++.net
I don't know if there is a way to make it less bad, I guess if you avoid multiple inheritance like the plague (which is otherwise a useful language feature) and reimplement the stdlib it would be better. But really if that is what you are after you are probably using the wrong language for the task.
Java and C# are much better suited to this style of programming.
#note if I have read your question wrong just delete this answer.
Check out Dynamic C++
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)