I have several views in my app, that are almost the same, so I decided to create a CBaseView class and to not copy the code. So I have something like this:
template <class BASE_T, class BASE_DOC, class BASE_DLG>
class CBaseView : public CListView
{
DECLARE_DYNCREATE(CBaseView<BASE_T, BASE_DOC, BASE_DLG>)
void func1()
{
// GetData() is just another method in CBaseView
BASE_T oData = GetData();
...
}
void func2()
{
BASE_DOC* pDocument = (BASE_DOC*) CView::GetDocumet();
pDocument->DoSomething();
...
}
void func3()
{
...
BASE_DLG oBaseDlg();
oBaseDlg.DoModal();
...
}
}
IMPLEMENT_DYNCREATE(CBaseView<BASE_T, BASE_DOC, BASE_DLG>, CListView)
After that I want to use the CBaseView for the others views:
CMyView : public CBaseView <MyType, MyDocument, MyDlg> {...};
The problem is coming with:
DECLARE_DYNCREATE(CBaseView<BASE_T, BASE_DOC, BASE_DLG>)
and
IMPLEMENT_DYNCREATE(CBaseView<BASE_T, BASE_DOC, BASE_DLG>, CListView)
It gаve me some strange errors. I saw that I can't use this macros with a template class. Also found a similar topic, but I'm quite new in MFC (and in programming like all) and I can't rewrite it so to works for my three template arguments.
I'm worried that I tried everything I could think of and still haven't done it. I really need to find a way to do it or at least an alternative, so guys please help me!
I don't know MFC, but the problem is quite clear: The macros do not accept template instantiations. This is understandable, because macros are expanded first and once you instantiate the template, you wont have CBaseView<BASE_T, BASE_DOC, BASE_DLG> but something like CBaseView<Foo,FooDoc,FooDlG>, ie concrete types for the parameter.
DECLARE_DYNCREATE is to enable creation of instances on the fly at runtime, while templates only exist at compiletime, so at some point you'll need to decide what instantiations of the template you want to use at runtime. You could keep the implementation in the template, but for the types used with the framework you use:
class View1 : public CBaseView<Foo1,FooDoc1,FooDlg1> {
DECLARE_DYNCREATE(View1)
};
IMPLEMENT_DYNCREATE(View1,CListView)
class View2 : public CBaseView<Foo2,FooDoc2,FooDlg2> {
DECLARE_DYNCREATE(View2)
};
IMPLEMENT_DYNCREATE(View2,CListView)
Related
I'm currently working on a project where everything is horribly mixed with everything. Every file include some others etc..
I want to focus a separating part of this spaghetti code into a library which has to be completely independent from the rest of the code.
The current problem is that some functions FunctionInternal of my library use some functions FunctionExternal declared somewhere else, hence my library is including some other files contained in the project, which is not conform with the requirement "independent from the rest of the code".
It goes without saying that I can't move FunctionExternal in my library.
My first idea to tackle this problem was to implement a public interface such as described bellow :
But I can't get it to work. Is my global pattern a way I could implement it or is there another way, if possible, to interface two functions without including one file in another causing an unwanted dependency.
How could I abstract my ExternalClass so my library would still be independent of the rest of my code ?
Edit 1:
External.h
#include "lib/InterfaceInternal.h"
class External : public InterfaceInternal {
private:
void ExternalFunction() {};
public:
virtual void InterfaceInternal_foo() override {
ExternalFunction();
};
};
Internal.h
#pragma once
#include "InterfaceInternal.h"
class Internal {
// how can i received there the InterfaceInternal_foo overrided in External.h ?
};
InterfaceInternal.h
#pragma once
class InterfaceInternal {
public:
virtual void InterfaceInternal_foo() = 0;
};
You can do like you suggested, override the internal interface in your external code. Then
// how can i received there the InterfaceInternal_foo overrided in External.h ?
just pass a pointer/reference to your class External that extends class InterfaceInternal. Of course your class Internal needs to have methods that accept InterfaceInternal*.
Or you can just pass the function to your internal interface as an argument. Something around:
class InterfaceInternal {
public:
void InterfaceInternal_foo(std::function<void()> f);
};
or more generic:
class InterfaceInternal {
public:
template <typename F> // + maybe some SFINAE magic, or C++20 concept to make sure it's actually callable
void InterfaceInternal_foo(F f);
};
edit: Added the cast-problem.
I have a small C++ problem and hope you can help me with it.
I'm using a library that provides a class GenericHandler. I have to inherit from that class, override stuff and then register my handler with the library to get the magic running. As I need multiple handlers that overlap in some areas, I tried to use templates as follows
template <typename T>
class MyGenericHandler : public GenericHandler
{
// everything used for all handlers goes here
};
class MyIntHandler : public MyGenericHandler<int>
{
};
class MyFloatHandler : public MyGenericHandler<float>
{
};
// in main
std::shared_ptr<MyIntHandler> handler = std::make_shared<MyIntHandler>();
library::HandlerQueue.register(handler);
// error-message: "no viable conversion from shared_ptr<MyIntHandler> to shared_ptr<GenericHandler>.
// Same error if I try it like this:
std::shared_ptr<GenericHandler> handler = std::make_shared<MyIntHandler>();
However, I now can't cast MyIntHandler into the library provided GenericHandler anymore.
It did work before, when I had MyIntHandler : public GenericHandler, so I guess the template somehow broke stuff.
Is there a way to still get it working? Do I need to cast manually, if yes how would I best do that?
Got it fixed by using std::dynamic_pointer_cast it seems; still unsure why #prehistoricpenguin couldn't reproduce it though.
I have this weird problem in which I want to have a collection of sub-classes of the class Script. But the thing is I can't know the type of this sub-classes because they're programmed by another person (It's a kind of a hotspot for my framework). So I used a template function but this is not my strong thing and it gives me an Unresolved external symbol.
I don't even know how to search this on other questions in SO.
Here's the code that tries to add the subclass of Script to the Scripts vector:
template <class T>
T* GameObject::addComponent()
{
T *t = new T(this);
Script *s = dynamic_cast<Script*> (&t);
if (s)
{
scripts.push_back(t);
return t;
}
return nullptr;
}
It is casted to Script to prevent other kinds of objects being trapped by this generic function.
It is called like this:
Cube->addComponent<myScript>();
Where myScript is subclass of Script.
Please correct me if I'm programming horrible code!
If I understand you correctly, you have something like this for MyScript:
class MyScript : public Script
{
...
};
Then GameObj can just receive a pointer to a Script:
GameObject::addComponent(Script * s)
{
scripts.push_back(t);
}
And you'd call it like this:
cube->addComponent(new MyScript);
I have a class,
class Ticket : public cocos2d::CCNode, public cocos2d::CCTargetedTouchDelegate { ... };
Which works fine when I register for touch events on that node using:
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(ticket_, 0, true);
However, if I alter my class so that it uses composition rather than inheritance for the CCNode bit:
class Ticket : public cocos2d::CCTargetedTouchDelegate {
private:
cocos2d::CCNode* node_;
public:
Ticket() { node_ = new CCNode(); node_->init(); }
cocos2d::CCNode* node() { return node_; }
...
};
Then the following blows up with a SIGSEGV 11:
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(ticket_, 0, true);
I have added ticket_->node() to the current layer, but I am wondering if the touch dispatcher somehow doesn't like the node and the delegate to be different things. Or to put it another way, is touch dispatcher is expecting the node and the delegate to be the same thing?
So in short, my code works when I use multiple inheritance, but it doesn't when I use composition. Without delving into the framework, can anyone say that this is true, or have I just missed something obvious? I am using cocos2d-2.1rc0-x-2.1.2
Yes, it seems cocos2d-x indeed does force multiple inheritance. It expects the touch delegate to be dynamically castable to a CCObject, which your Ticket class isn't when you use composition. When you inherit from CCNode, which itself inherits from CCObject, you're in the clear. You can see the problem here on github.
This does not seem to be a mistake though, since the documentation actually hints at this by noting
IMPORTANT: The delegate will be retained.
for CCTouchDispatcher::addTargetedDelegate.
This has been really killing me for the last couple of days now.
I effectively have something like what Szymon Gatner explained in his fantastic article, found here. (Check out the EventHandler class in the demo code there)
This is one of the few articles I've found on the web that do a good job explaining
how to create a type with an expandable interface. I particularly liked the resulting usage syntax, quite simple to understand.
However, I have one more thing I want to do with this type, and that is to allow it to be decorated. Now, to decorate it with extra data members is one thing, but I'd like to allow the decoration to expand the interface as well, with the function EventHandler::handleEvent being the only method required to be exposed publicly.
Now, unfortunately, the EventHandler::registerEventFunc method is templated.
This means that I cannot define it as a virtual method in some even more base class that EventHandler would inherit from, such as HandlerBase.
My question is whether or not someone has any good ideas on how to solve the problem (making EventHandler decorateable).
I've tried creating methods
1)
void registerEventFunc(boost::function<void()> * _memFn);
and
2)
void registerEventFunc(boost::function<void(*SomeDerivedEvent*)> * _memFn);
and
3)
void registerEventFunc(boost::function<void(EventBase*)> * __memFn);
For 1, if I do that, I lose the typeid of the callback's class Event derived argument type.
For 2, I'd have to overload the function for as many Event callbacks this class plans on registering
For 3, Polymorphism does't work in template parameters ( do correct me if I'm wrong ).
The closest I've come to allowing the function to be made virtual is with 1,
, but I have to bind the argument to the boost::function at the boost::function object's creation and can't use lambda on it later in the body of EventHandler::handleEvent.
class FooEvent : public Event
{
public:
FooEvent(int _val) : Event(), val(_val){}
int val;
};
class MyHandler : public EventHandler
{
public:
MyHandler()
{
registerEventFunc(new boost::function<void()>(boost::bind(boost::mem_fn(&MyHandler::onEvent),this, new FooEvent(5))));
}
void onEvent(const FooEvent * _event)
{
cout << _event->val << endl;
}
};
Ultimately, I don't think that works though ( it can't figure out that whole typeInfo business to create the key for the map lookup)
Any ideas would be greatly appreciated!
If I'm going about this the wrong way, I would be grateful for the mention of alternatives.
The goal in the end of course is to have a decoratable type that can expand it's public interface easily as well as it's data members.
I thought Szymon's stuff was a good starting point since it seemed to have the 2nd half done already.
Thank you ahead of time for any assistance.
Perhaps one option would be to create a templated public function that preserves type information, plus a virtual protected function for actually registering the handler. That is:
class event_source {
protected:
struct EventAdapter {
virtual void invoke(EventBase *) = 0;
virtual ~EventAdapter() { }
};
template<typename EventParam>
struct EventAdapterInst : public EventAdapter {
boost::function<void(const EventParam &)> func_;
EventAdapterInst(const boost::function<void(const EventParam &)> &func)
: func_(func)
{ }
virtual void invoke(EventBase *eb) {
EventParam *param = dynamic_cast<EventParam *>(eb);
assert(param);
func_(*param);
}
};
virtual void register_handler(std::type_info param_type, EventAdapter *ea);
public:
template<typename EventParam>
void register_handler(const boost::function<const EventParam &> &handler)
{
register_handler(typeid(EventParam), new EventAdapterInst(handler));
}
};
Derived classes can override the virtual register_handler to do whatever they like without breaking the type inference properties of the template function.