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)
Related
I'm trying to implement a Property system in my project similar to Property system in Qt. We just started with some ideas and are in prototyping stage.
Basically, what I understood from Qt is, client should be able to pass the get function, set function and property type through some macro in the .h file. So I tried to mimic the same.
Following is my sample code:
Abstract getter class. This type of getter class is a member in Property Class
class AbstractFunc
{
public:
template < typename R >
R Invoke ()
{
return (this)->Invoke ();
}
};
Get Function template: Return values can be T , T&, const T& , T* etc..
template < typename R, class T > class GetterFunction : public AbstractFunc
{
typedef R (T::*GetterFunc) ();
public:
GetterFunction (T * obj, GetterFunc func):m_Obj (obj), m_Func (func)
{
}
R Invoke ()
{
return m_Obj->*(m_Func) ();
}
public:
T * m_Obj;
GetterFunc m_Func;
};
Property Class:
class Property
{
public:
Property (string name, AbstractFunc* getter):m_name (name), m_getter (getter)
{
}
template < typename R > R GetValue ()
{
return m_getter->Invoke < R > ();
}
private:
string m_name;
AbstractFunc* m_getter;
};
Some Window Class:
class Window
{
public:
};
Example window class
class CheckBox :public Window
{
public:
int GetChecked ()
{
return m_checked;
}
void SetChecked (int nChecked)
{
m_checked = nChecked;
}
void AddProperty (string name)
{
m_prop = new Property (name, new GetterFunction< int, Checked >(this, &Checked::GetChecked));
}
int m_checked;
Property *m_prop;
};
main function:
int main ()
{
CheckBox cc;
cc.AddProperty ("Hello");
cout<<"value:"<< cc.m_prop->GetValue<int>();
return 0;
}
PROBLEM:
Getter function is remembered as AbstractFunc in Property Class. I want to call 'Invoke' on AbstractFunc* instance and it should invoke the member function and return correct return type. The above code throws error at AbstractFunc::Invoke.
see live
Your AbstractFunc isn't abstract at all: its Invoke isn't virtual. So even though GetterFunction also has a method named Invoke, that method doesn't actually override AbstractFunc::Invoke; it just hides it. When you try to call Invoke through the AbstractFunc*, it calls AbstractFunc::Invoke, which goes into infinite recursion and thus produces UB.
I would follow #n.m.'s suggestion to make a class hierarchy like so:
class AbstractFunc {
// lock down construction
AbstractFunc() = default;
public:
template<typename R>
R Invoke();
template<typename R>
bool HasType() const noexcept;
virtual ~AbstractFunc() = default; // need to have SOME virtual method so that we have runtime type info; also a virtual destructor is required anyway
template<typename R>
friend class TypedFunc;
};
template<typename R>
struct TypedFunc : AbstractFunc { // the ONLY instances of AbstractFunc are also instances of specializations of TypedFunc
virtual R InvokeTyped() = 0;
};
// one kind of TypedFunc applies a getter on an object
template<typename R, typename T>
struct GetterFunc : TypedFunc<R> {
// you never see a GetterFunc in the interface anyway... don't see a need to hide these
T *obj; // have you considered std::shared_ptr?
R (T::*getter)();
GetterFunc(T *obj, R (T::*getter)()) : obj(obj), getter(getter) { }
R InvokeTyped() override { return (obj->*getter)(); }
};
template<typename R, typename T>
std::unique_ptr<GetterFunc<R, T>> MakeGetterFunc(T *obj, R (T::*getter)()) {
return std::make_unique<GetterFunc<R, T>>(obj, getter);
}
// another kind applies a functor, etc.
template<typename R, typename F>
struct FunctorFunc : TypedFunc<R> {
F func;
template<typename... G>
FunctorFunc(G&&... args) : func(std::forward<G>(args)...) { }
R InvokeTyped() override { return func(); }
};
This is already usable: if you have an AbstractFunc* or an AbstractFunc&, you can dynamic_cast it down to a TypedFunc of the expected type (e.g. TypedFunc<int>). If that succeeds (you get a nonnull pointer or there is no std::bad_cast exception), then you just call InvokeTyped without having to know what kind of GetterFunc/FunctorFunc/whatever you are actually dealing with. The functions Invoke and HasType declared in AbstractFunc are just sugar to help do this.
template<typename R>
bool AbstractFunc::HasType() const noexcept {
return dynamic_cast<TypedFunc<R> const*>(this);
}
template<typename R>
R AbstractFunc::Invoke() {
return dynamic_cast<TypedFunc<R>&>(*this).InvokeTyped();
// throws std::bad_cast if cast fails
}
Done.
class Property {
std::string name;
std::unique_ptr<AbstractFunc> getter;
public:
Property(std::string name, std::unique_ptr<AbstractFunc> getter) : name(std::move(name)), getter(std::move(getter)) { }
template<typename R>
bool HasType() const noexcept { return getter->HasType<R>(); }
template<typename R>
R GetValue() const { return getter->Invoke<R>(); }
std::string const &GetName() const noexcept { return name; }
};
struct Window {
virtual ~Window() = default;
// doesn't really make sense to add/remove these from outside...
virtual std::vector<Property> GetProperties() = 0;
};
class CheckBox : public Window {
int checked = 0;
public:
int GetChecked() /*const*/ noexcept { return checked; }
void SetChecked(int checked) noexcept { this->checked = checked; }
std::vector<Property> GetProperties() override {
std::vector<Property> ret;
ret.emplace_back("Boxes Checked", MakeGetterFunc(this, &CheckBox::GetChecked));
return ret;
}
};
int main() {
CheckBox cb;
cb.SetChecked(5);
for(auto const &prop : cb.GetProperties()) std::cout << prop.GetName() << ": " << prop.GetValue<int>() << "\n";
}
You could then add e.g. a virtual std::type_info const& GetType() const or similar to AbstractFunc if you want to be able to directly get at the type, etc.
I need a template function that can serve generic purpose of accessing a member variable and operating functions present in that member variable. I have a set of functions to be called and this will solve my purpose.
I have tried the following
class Utilities {
public:
template<typename Container, typename MemberVar, typename Operator>
static void for_all(Container& C, MemberVar memvar, Operator Op) {
for (auto& element : C) {
(element.memvar->Op)();
}
}
};
I have the following test code where there is class Test that has PrivateImpl and DataStructure holding that privatimpl.
Below is the print function that calls the Utilities::for_all function with privateimpl's print function
void Test::print() {
::Utilities::for_all(m_vec_struct_privateimpl,&Test::Struct_PrivateImpl::m_privateimpl,&Test::CPrivateImpl::print);
}
Below is the details about all the classes
// Main Class
class Test {
public:
Test();
~Test();
void print();
private:
class CPrivateImpl;
struct Struct_PrivateImpl;
std::vector<Struct_PrivateImpl> m_vec_struct_privateimpl;
}; //class Utilities
// Class PrivateImpl
class Test::CPrivateImpl {
public:
CPrivateImpl(std::initializer_list<int>& lst) {
for (auto& i : lst) {
m_vec_int.push_back(i);
}
}
void print(int i) {
cout << i << " ";
}
private:
std::vector<int> m_vec_int;
}; //class Test::CPrivateImpl
// Data Structure having PrivateImpl
struct Test::Struct_PrivateImpl {
public:
Struct_PrivateImpl(int i) {
m_privateimpl = std::make_shared<Test::CPrivateImpl>(std::initializer_list<int>{100+i,200+i,300+i});
};
~Struct_PrivateImpl() {
}
//private:
std::shared_ptr<CPrivateImpl> m_privateimpl;
}; // class WiperSkeletonSomeIP::Struct_PrivateImpl
Test::Test(){
for(auto i = 0u; i != 3; ++i) {
Struct_PrivateImpl a_struct_pvtimpl(i);
m_vec_struct_privateimpl.push_back(a_struct_pvtimpl);
}
}
void Test::print() {
::Utilities::for_all(m_vec_struct_privateimpl,&Test::Struct_PrivateImpl::m_privateimpl,&Test::CPrivateImpl::print);
}
// This is the main function
int main() {
Test t;
t.print();
}
I am getting error message saying memvar has function Op.
This is an example code I have a lot of functions to be called within PrivateImpl class.
Please help me how to solve this.
Syntax to acces via member pointer is .* or ->*:
class Utilities {
public:
template <typename Container, typename MemberVar, typename Operator>
static void for_all(Container& C, MemberVar memvar, Operator Op)
{
for (auto& element : C) {
((*(element.*memvar)).*Op)();
}
}
};
Demo
I have written a small piece of code where I am able to call setter and getter functions packed within a functoid using mem_fun templates.
I now would like to use this approach on top of a class hierarchy where every class might have getter and setter which can be registered as pair within a vector or array to be able to call the getter and setter if needed. GUIObject and GUICompositeObject are example classes out of the described class hierarchy.
The bound_mem_fun_t for the objects have unfortunately different types and thats the reason I don't know how to integrate them into an array/vector of pointers to the functors.
In c++11 I would use std::function. Is there a way to emulate this in c++98?
Because our compiler support only c++98 I cannot use the new features of c++11 or c++14. Also boost is not allowed.
#include <functional>
class GUIObject
{
int m_Alpha;
public:
void SetAlpha(int a) { m_Alpha = a;};
int GetAlpha() {return m_Alpha;};
};
class GUICompositeObject: public GUIObject
{
int m_NumOfChilds;
public:
void SetNumOfChilds(int NumOfChilds) { m_NumOfChilds = NumOfChilds;};
int GetNumOfChilds() {return m_NumOfChilds;};
};
template<typename T>
struct bound_mem_fun_t
{
bound_mem_fun_t(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o) :
m_GetFunc(GetFunc), m_SetFunc(SetFunc), obj(o) { } ;
int operator()() { return m_GetFunc(obj); } ;
void operator()(int i) { m_SetFunc(obj, i); } ;
std::mem_fun_t<int, T> m_GetFunc;
std::mem_fun1_t<void, T, int> m_SetFunc;
T* obj;
};
int main()
{
GUIObject kGUIObject;
GUICompositeObject kCompObj;
bound_mem_fun_t<GUIObject> GUIObjectFunc(std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject);
GUIObjectFunc(17);
int ii = GUIObjectFunc();
bound_mem_fun_t<GUICompositeObject> GUICompObjectFunc(std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj);
GUICompObjectFunc(17);
int iChilds = GUICompObjectFunc();
return 0;
}
Here is the complete solution after #filmors answer:
#include <functional>
#include <vector>
#include <iostream>
class GUIObject
{
int m_Alpha;
public:
void SetAlpha(int a) { m_Alpha = a;};
int GetAlpha() {return m_Alpha;};
};
class GUICompositeObject: public GUIObject
{
int m_NumOfChilds;
public:
void SetNumOfChilds(int NumOfChilds) { m_NumOfChilds = NumOfChilds;};
int GetNumOfChilds() {return m_NumOfChilds;};
};
struct bound_mem_fun_base
{
virtual int operator()() =0;
virtual void operator()(int) =0;
};
template<typename T>
struct bound_mem_fun_t : public bound_mem_fun_base
{
bound_mem_fun_t(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o) :
m_GetFunc(GetFunc), m_SetFunc(SetFunc), obj(o) { } ;
virtual int operator()() { return m_GetFunc(obj); } ;
virtual void operator()(int i) { m_SetFunc(obj, i); } ;
std::mem_fun_t<int, T> m_GetFunc;
std::mem_fun1_t<void, T, int> m_SetFunc;
T* obj;
};
template<typename T> bound_mem_fun_t<T>* make_setter(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o)
{
return new bound_mem_fun_t<T> (GetFunc, SetFunc, o);
}
int main()
{
GUIObject kGUIObject;
GUICompositeObject kCompObj;
std::vector<bound_mem_fun_base*> kBoundVector;
kBoundVector.push_back(new bound_mem_fun_t<GUIObject> (std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject));
kBoundVector.push_back(new bound_mem_fun_t<GUICompositeObject> (std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj));
kBoundVector.push_back(make_setter<GUIObject> (std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject));
kBoundVector.push_back(make_setter<GUICompositeObject> (std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj));
for (int i = 0; i < 4 ; i++)
{
(*kBoundVector[i])(i*10);
int res = (*kBoundVector[i])();
std::cout << "Getter result " << res << "\n";
}
return 0;
}
Unfortunately the make_setter function does not really shorten the creation of the functor. Any ideas will be welcome.
Just give your bound_mem_fun_t<T> a common base class and use dynamic dispatch to solve your problem:
struct bound_mem_fun_base {
virtual int operator()() = 0;
virtual void operator()(int) = 0;
};
template <typename T>
struct bound_mem_fun_t : bound_mem_fun_t ...
Then you can keep pointers to bound_mem_fun_base in your vector and call the elements as (*v[0])().
Also, TR1 does contain std::tr1::function, is that available?
First a remark on std::function from c++11: That will not solve your problem, because you need an already bounded function pointer. This pointer must be bound to your object. I believe what you need is an own implementation to std::bind.
I started only a very! small Binder class which is hopefully a starting point for your needs. If you need to have template parameter lists in older c++ versions, take a look for loki. http://loki-lib.sourceforge.net/
As a hint I can give you a short example of what i did:
class A
{
private:
int val;
public:
A(int i): val(i) {}
void Do(int i) { std::cout << "A " << val<< " " << i << std::endl; }
};
class B
{
private:
int val;
public:
B(int i): val(i){}
void Go(int i) { std::cout << "B " << val << " " << i << std::endl; }
};
class Base
{
public:
virtual void operator()(int i)=0;
};
template <typename T>
class Binder: public Base
{
void (T::*fnct)(int);
T* obj;
public:
Binder( void(T::*_fnct)(int), T*_obj):fnct(_fnct),obj(_obj){}
void operator()(int i)
{
(obj->*fnct)(i);
}
};
int main()
{
A a(100);
B b(200);
// c++11 usage for this example
//std::function<void(int)> af= std::bind( &A::Do, &a, std::placeholders::_1);
//af(1);
// hand crafted solution
Base* actions[2];
actions[0]= new Binder<A>( &A::Do, &a);
actions[1]= new Binder<B>( &B::Go, &b);
actions[0]->operator()(55);
actions[1]->operator()(77);
}
I have implemented a Policy using the CRTP. The policy requires the Base class to have a function called foo:
template<typename Base>
struct Policy<Base> {
// ...
Base* b(){ return static_cast<Base*>(this); }
void do(){ b()->foo(); }
};
I have one class called Widget that uses my policy. Widget implements foo and everything is fine:
struct Widget : Policy<Widget> {
// ...
void foo();
};
The problem: I also have a type called OldWidget that implements the functionality of foo in a function named oldFoo:
struct OldWidget : Policy<OldWidget> {
// ...
void oldFoo();
};
I don't want to modify OldWidget (besides extending it with the policy). I don't want to use an AdaptedOldWidget:
struct AdaptedOldWidget : OldWidget, Policy<AdaptedOldWidget> {
void foo(){ oldFoo(); }
};
The best would be to extend my existing policy_traits class to something like:
template<typename T>
struct policy_traits {};
template<>
struct policy_traits<Widget> {
// typedefs...
member_function_name = foo;
};
template<>
struct policy_traits<OldWidget> {
// typedefs
member_function_name = oldFoo;
};
Such that I can implement the Policy like this:
template<typename Base>
struct Policy<Base> {
// ...
Base* b() { return static_cast<Base*>(this); }
void do(){ b()->policy_traits<Base>::member_function_name(); }
};
Is there away to achieve something like this in C++?
Proposed solution: I could do the following:
template<typename Base>
struct Policy<Base> : Policy_Member_Traits<Base> {
// ...
Base* b(){ return static_cast<Base*>(this); }
void do(){ foo_wrapper(); }
};
template<typename T> struct Policy_Member_Traits { };
template<> struct Policy_Member_Traits<Widget> {
void foo_wrapper(){ static_cast<T*>(this)->foo(); }
};
template<> struct Policy_Member_Traits<OldWidget> {
void foo_wrapper(){ static_cast<T*>(this)->oldFoo(); }
};
There must be hopefully a better easier way to achieve this.
first of all: signature of all functions must be the same. then you may set a static member w/ member-function address inside of your policy_traits, so you'll be able to call desired function later (from your Policy template) using it.
typedef void (*void_memfn_type)();
template<>
struct policy_traits<Widget> {
static void_memfn_type const member_function_name = &Widget::foo;
};
template<>
struct policy_traits<OldWidget> {
static void_memfn_type const member_function_name = &OldWidget::oldFoo;
};
then:
template<typename Base>
struct Policy<Base> {
// ...
Base* b() { return static_cast<Base*>(this); }
void do(){ b()->policy_traits<Base>::(*member_function_name)(); }
};
Here's an example how specializing selectively. First, some example classes:
#include <iostream>
struct Foo
{
void foo() const { std::cout << "Foo::foo\n"; }
void bar() const { std::cout << "Foo::foo\n"; }
};
struct Biz
{
void old_foo() const { std::cout << "Fiz::old_foo\n"; }
void bar() const { std::cout << "Fiz::foo\n"; }
};
struct Fiz
{
void foo() const { std::cout << "Biz::foo\n"; }
void old_bar() const { std::cout << "Biz::old_foo\n"; }
};
Now the trait:
template <typename T> struct Dispatch
{
static void foo(T const & x) { x.foo(); }
static void bar(T const & x) { x.bar(); }
};
template <> void Dispatch<Biz>::foo(Biz const & x) { x.old_foo(); }
template <> void Dispatch<Fiz>::bar(Fiz const & x) { x.old_bar(); }
And here's a usage example:
template <typename T> void dispatch(T const & x)
{
Dispatch<T>::foo(x);
Dispatch<T>::bar(x);
}
int main()
{
Foo f;
Biz b;
Fiz c;
dispatch(f);
dispatch(b);
dispatch(c);
}
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++