Alternatives to virtual index implementation in a model - c++

So I have again encountered the limits of QObjects that cannot be mixed with templates (at least not directly). Basically I have a proxy model class that uses indexing to translate the source positions to local positions and back. The index can be implemented in number of ways, for now I need two versions, one using QHash and one using QVector. The interface of the index is common to both with only subtle differences regarding index manipulation. With templates this would be easy, I would make the class a template and then used specialization for these two cases.
However the model needs to be a QObject so instead it seems I would need to use polymorphism like so:
class IndexInterface;
class VectorIndex; //inherits IndexInterface
class HashIndex; //inherits IndexInterface
class ProxyModel : public QObject
{
Q_OBJECT
public:
enum IndexType { Vector, Hash };
explicit ProxyModel(IndexType indexType, QObject *parent = 0) :
QObject(parent),
index(indexType == Vector ? new VectorIndex : new HashIndex)
{
}
//...
private:
IndexInterface *index = nullptr;
};
I have couple of issues with this. First, it requires dynamic allocation of the index which I would like to get rid off. Second, because of the use of pointer to IndexInterace to dispatch the calls to the index no method of the index will ever be inlined (I have looked over dissasembled code to confirm this and tried various optimizations etc. to no avail).
What would be the alternatives to this design ideally without dynamic allocation of the index and without virtual calls to the index?

Make the index-type-specific class one of the base classes:
template <typename Index> class IndexHandler {
};
using VectorIndexHandler = IndexHandler<QVector>;
using HashIndexHandler = IndexHandler<QHash>;
class VectorIndexProxy : public QAbstractItemModel, VectorIndexHandler {
... // should be very small
};
class HashIndexProxy : public QAbstractItemModel, HashIndexHandler {
... // should be very small
};
Then instead of passing the index type to the constructor, use a factory function:
QAbstractItemModel * proxyFactory(IndexType indexType, QObject * parent = 0) {
switch (indexType) {
case Foo::Vector:
return new VectorIndexProxy(parent);
...
}
}
If you envision an interface broader or different than QAbstractItemModel, you'll need to write such a base class and derive from it in the concrete implementations, of course.
You could use CRTP if needed for IndexHandler to call directly into the derived class's methods, making it even smaller:
template <typename Index, typename Derived> class IndexHandler {
Derived * derived() { return static_cast<Derived*>(this); }
const Derived * derived() const; // as above
void foo() {
derived()->setObjectName("Yay");
}
};
class VectorIndexProxy :
public QAbstractItemModel,
public VectorIndexHandler<QVector, VectorIndexProxy>
{
... // should be very small
};
You can also "promote" methods from the base class to be Qt slots:
class VectorIndexProxy : ... {
#ifdef Q_MOC_RUN
Q_SLOT void foo();
#endif
};
See this question about having a base non-QObject class with signals and slots.
Finally, you could use the PIMPL idiom, and have a concrete implementation of a fixed type just like you desire. The factory would be invoked in the constructor and you'd be swapping in different PIMPLs for different indices. That's not as expensive as you think since all Qt classes already dynamically allocate a PIMPL, so you can piggy-back on that allocation by deriving your PIMPL from QObjectPrivate (#include <private/qobject_p.h>), and passing the instance of the PIMPL to the protected QObject(QObjectPrivate&). This pattern is omnipresent in Qt, so even though it's an implementation detail, it's not going away in Qt 5 at the very least. Here's a rough sketch:
// ProxyModel.cpp
#include <private/qobject_p.h>
class ProxyModelPrivate : public QObjectPrivate {
// Note: you don't need a q-pointer, QObjectData already provides it
// for you! CAVEAT: q-pointer is not valid until the QObject-derived-class's
// constructor has returned. This would be the case even if you passed
// the q-pointer explicitly, of course.
...
}; // base class
class VectorProxyModelPrivate : public ProxyModelPrivate { ... };
class ProxyModel : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(ProxyModel)
ProxyModel * pimpl(IndexType indexType) {
switch (indexType) {
case Vector: return new VectorProxyModelPrivate();
...
}
public:
enum IndexType { Vector, Hash };
explicit ProxyModel(IndexType indexType, QObject *parent = 0) :
QObject(*pimpl(IndexType), parent)
{}
};
If you were deriving from QAbstractItemModel, your PIMPL would derive from QAbstractItemModelPrivate, in the same fashion; this works for any QObject-deriving class in Qt!

Related

What is the most generic way to link two independent classes without extra code?

There's a hierarchy of classes describing different properties of some object. The abstract class Property is a base class, and it has children: IntegerProperty, BooleanProperty, and so on. All data is encoded in QString and derived classes decode it in their own way.
class Property : public QObject
{
Q_OBJECT
public:
// ...
virtual QString value() const = 0;
virtual bool setValue(const QString &value) = 0;
virtual bool validateValue(const QString& value) = 0;
// ...
};
class IntegerProperty : public Property
{
// ...
virtual QString value() const override;
virtual bool setValue(const QString &value) override;
virtual bool validateValue(const QString& value) override;
// ...
};
// ...
Every property class must have an independent editor (GUI widget) - PropertyEditor (abstract class again), IntegerPropertyEditor, BooleanPropertyEditor, and so on.
class PropertyEditor : public QWidget
{
Q_OBJECT
public:
inline Facer::PropertyPointer attachedProperty() { return m_property; }
protected:
PropertyEditor(Facer::PropertyPointer attachedProperty, QWidget* parent = nullptr);
virtual void mousePressEvent(QMouseEvent* event) override;
virtual bool eventFilter(QObject *watched, QEvent *event) override;
// ...
};
class IntegerPropertyEditor : public PropertyEditor
{
// ...
};
// ...
For example, I have a set of different properties. I don't know which exactly properties I have because they are all pointers to Property class. My task is to create specified editors of these properties, so I need to get IntegerPropertyEditor if the property object is IntegerProperty.
for (Property* property : propertySet())
PropertyEditor* editor = createEditor(property);
I made a temporary workaround with macro:
#define IF_TYPE_GET_EDITOR(propertyType, editorType) \
if (std::dynamic_pointer_cast<propertyType>(property)) \
return new editorType(property, this);
// ...
PropertyEditor *PropertySetWidget::create(PropertyPointer property)
{
IF_TYPE_GET_EDITOR(BooleanProperty, BooleanPropertyEditor)
else IF_TYPE_GET_EDITOR(ColorProperty, ColorPropertyEditor)
else IF_TYPE_GET_EDITOR(FloatingPointProperty, FloatingPointPropertyEditor)
else IF_TYPE_GET_EDITOR(FontProperty, FontPropertyEditor)
else IF_TYPE_GET_EDITOR(IntegerProperty, IntegerPropertyEditor)
else IF_TYPE_GET_EDITOR(TextProperty, TextPropertyEditor)
else throw std::runtime_error("This PropertyType is not implemented yet");
}
It doesn't look like a good solution - if I add a new type of property and its editor, I'll have to update this code as well. What is the most convenient and generic way to link an editor class and a property class?
This might give some extra code, especially depending on how your project is set up, but one solution is to make a virtual function in Property that returns a pointer to an editor:
class Property : public QObject
{
public:
virtual PropertyEditor* CreateEditor(PropertySetWidget* widget) {
// let's put our default behavior here
throw std::runtime_error("This PropertyType is not implemented yet");
}
//...
};
Now, you make each class responsible for supplying its own editor:
class IntegerProperty : public Property
{
public:
// doesn't have to be virtual, I don't think Just a regular version should be fine too.
virtual PropertyEditor* CreateEditor(PropertySetWidget* widget) {
return new IntegerPropertyEditor(this, widget);
}
//...
};
Depending on how many classes you have, that may be a lot of copying and pasting.
However, the fun part is PropertySetWidget::create():
PropertyEditor *PropertySetWidget::create(PropertyPointer property)
{
return property->CreateEditor(this);
}
Because every child of property is responsible for supplying its own editor, we don't have to worry about it at this level. If one doesn't exist/isn't implemented, property::CreateEditor() will throw an error for you. If one does exist/is implemented, it will return a pointer to a new instance the editor automatically.
The big advantage is that if you add a new property and its editor, you don't have to touch it this function at all. The virtual function takes care of properly implementing it for you. If the new property has an editor, it just needs to overload that function, and this create() still works properly.
Of course, you will have to modify Property's interface this way, which may not be feasible in your case. That's the major drawback to this approach.
What you want requires Reflection implemented, although there are rather cumbersome and ugly ways to implement what you wanted without macros. I personally recommend the solution of #Chipster.
If you are still interested in methods that do not require Property to provide its own editor... I wrote an example, you can check it out.
#include <iostream>
#include <memory>
class A
{ //virtual working class
public:
virtual ~A() = default;
};
//two possible implementations
class B : public A {};
class C : public A {};
//Editor interface
class EditorA
{
public:
virtual ~EditorA() = default;
virtual void print() = 0;
};
//Implementations of editors
class EditorB :
public EditorA
{
public:
void print() override
{
std::cout << "Editor B\n";
}
};
class EditorC :
public EditorA
{
public:
void print() override
{
std::cout << "Editor C\n";
}
};
//template class used for declaring which Editor you use depending on the class you provide
// I would make a namespace but there are no template namespaces
template<typename T>
class EditorT;
template<>
class EditorT<B>
{
public:
using EditorType = EditorB;
};
template<>
class EditorT<C>
{
public:
using EditorType = EditorC;
};
using namespace std;
// Recursive GetEditor code... written inside class as a static method for reasons.
template<typename... Args>
class CEditorIdentifier;
template<>
class CEditorIdentifier<>
{
public:
static EditorA * GetEditor(shared_ptr<A>& val)
{
return nullptr;
}
};
template<typename Arg, typename... Args>
class CEditorIdentifier<Arg, Args...>
{
public:
static EditorA * GetEditor(shared_ptr<A>& val)
{
if(std::dynamic_pointer_cast<Arg>(val))
{
return new typename EditorT<Arg>::EditorType;
}
return CEditorIdentifier<Args...>::GetEditor(val);
}
};
template<typename... Args>
EditorA* FindEditor(shared_ptr<A>& val)
{
return CEditorIdentifier<Args...>::GetEditor(val);
}
int main()
{
shared_ptr<A> b = make_shared<B>();
shared_ptr<A> c = make_shared<C>();
EditorA* eB = FindEditor<B,C>(b);
EditorA* eC = FindEditor<C,B>(c);
eB->print();
eC->print();
return 0;
}
Now you can add additional classes D,E,F... you only have to maintain the reference classes EditorT<D>, EditorT<E>, EditorT<F>...
Complicated right? Well... current features in C++ for such programming are limited. It's being worked and will be available in the future (see Reflection TS) but not now. Also it will be simpler to implement in C++20 with all the extensions to constexpr.
I like the answer above about each Property having a virtual method to return the appropriate type of editor. The only downside to that is that it may tie user interface-related elements into your lower-level code. Depending on your needs, that may or may not be OK.
A variation of your original factory that keeps the editor creation separate from the property class definitions is that you could add a "propertyType" virtual method that returns an integer, and then your factory becomes a switch statement:
switch (Property.propertyType ())
{
case BooleanPropertyType: create Boolean property editor
case StringPropertyType: create String properly editor
etc.
}
You would have an enum somewhere with the defined property type values. It's the same basic idea, but it avoids the overhead of the dynamic cast. (Whether or not it's actually faster is something to test.)
I don't think there's anything fundamentally wrong with your approach other than the possible dynamic_cast overhead, and often, I think that having a factory method where all of the editors are created for all of the types can be easier to maintain than creating the UI elements in classes where you're trying to manage data. Purists may see this as a violation of good object oriented classes, but it really depends on your needs and who you're trying to please.

Contravariant types and extensibility

I'm writing a C++ library for optimization, and I've encountered a curious issue with contra-variant types.
So, I define a hierarchy of "functions", based on what information they can compute.
class Function {
public:
double value()=0;
}
class DifferentiableFunction : public Function {
public:
const double* gradient()=0;
}
class TwiceDifferentiableFunction : public DifferentiableFunction {
public:
const double* hessian()=0;
}
Which is all well and good, but now I want to define interfaces for the optimizers. For example, some optimizers require gradient information, or hessian information in order to optimize, and some don't. So the types of the optimizers are contravariant to the types of the functions.
class HessianOptimizer {
public:
set_function(TwiceDifferentiableFunction* f)=0;
}
class GradientOptimizer : public HessianOptimizer {
public:
set_function(DifferentiableFunction* f)=0;
}
class Optimizer: public GradientOptimizer {
public:
set_function(TwiceDifferentiableFunction* f)=0;
}
Which I suppose makes sense from a type theoretic perspective, but the thing that is weird about it is that usually when people want to extend code, they will inherit the already existing classes. So for example, if someone else was using this library, and they wanted to create a new type of optimizer that requires more information than the hessian, they might create a class like
class ThriceDifferentiableFunction: public TwiceDifferentiableFunction }
public:
const double* thirdderivative()=0;
}
But then to create the corresponding optimizer class, we would have to make HessianOptimizer extend ThirdOrderOptimizer. But the library user would have to modify the library to do so! So while we can add on the ThriceDifferentiableFunction without having to modify the library, it seems like the contravariant types lose this property. This seems to just be an artifact of the fact the classes declare their parent types rather than their children types.
But how are you supposed to deal with this? Is there any way to do it nicely?
Since they're just interfaces, you don't have to be afraid of multiple inheritance with them. Why not make the optimiser types siblings instead of descendants?
class OptimizerBase
{
// Common stuff goes here
};
class HessianOptimizer : virtual public OptimizerBase {
public:
virtual set_function(TwiceDifferentiableFunction* f)=0;
}
class GradientOptimizer : virtual public OptimizerBase {
public:
virtual set_function(DifferentiableFunction* f)=0;
}
class Optimizer : virtual public OptimizerBase {
public:
virtual set_function(TwiceDifferentiableFunction* f)=0;
}
// impl
class MyGradientOptimizer : virtual public GradientOptimizer, virtual public HessianOptimizer
{
// ...
};

How to allow subclasses to have a common base class but accept different types of arguments in their methods

I hope the title best fits my question but I'll explain further.
I have two data types I'm using (a Matrix supported by the Eigen library and a pair of STL maps keyed by strings holding int values).
I would like to allow my code to work with both of them as generically as possible. So I started by creating an abstract base class including basic operations I required (insert, get "row" etc.) and trying to derive two sub classes to wrap my data types(one for matrix and one for my pair) implementing the inner functions as I needed.
This worked well for a while but then I encountered some typing problems, since my matrix is indexed by integers and the hash maps are indexed by strings (they both represent the same data type just in different ways).
When I attempted to write code that retrieved a "row" I was stuck since I know I can't declare a method in my base class and then override it with different argument types (the matrix retrieves a row by a numeric index and the maps retrieve it by string).
Is there a common way to do this without the overuse of templates for each subclass ?
A code example might make it clear (forgive any mistakes as this is just an example):
class BaseClass {
public:
virtual GenericRowType getRow(???? index)=0;
}
class MatrixWrapper : public BaseClass{
// Should be: GenericRowType getRow(int index);
}
class MapsWrapper : public BaseClass{
// Should be: GenericRowType getRow(string index);
}
You can use templates:
template <typename T>
class BaseClass {
public:
virtual GenericRowType getRow(T index)=0;
}
class MatrixWrapper : public BaseClass<int>{
// Should be: GenericRowType getRow(int index);
}
class MapsWrapper : public BaseClass<string>{
// Should be: GenericRowType getRow(string index);
}
This is a classical case for using templates. You should make the BaseClass a template with one class template parameter and then the inherited classes will inherit to a template specialization:
template <class T>
class BaseClass {
public:
virtual GenericRowType getRow(T index) = 0;
};
class MatrixWrapper : public BaseClass<int> {
public:
GenericRowType getRow(int index);
};
class MapsWrapper : public BaseClass<std::string> {
public:
GenericRowType getRow(std::string index);
};

Is there anything better than a metafactory to work around constructor injection into derived classes in CRTP?

In the CRTP, I want to inject the constructor into the derived class, cleanly - without use of macros and without writing it out. It seems it's impossible, so I've come up with some workarounds.
First, there's an underlying event class (QEvent) that should have a unique integer type tag for every derived class (see rationale). You obtain it by calling a registration function It's easy enough to create a CRTP wrapper that will hide this from you:
template <typename Derived> class EventWrapper : public QEvent {
public:
EventWrapper() : QEvent(staticType()) {}
static QEvent::Type staticType() {
static QEvent::Type type = static_cast<QEvent::Type>(registerEventType());
return type;
}
};
class MyEvent1 : public EventWrapper<MyEvent1> {}; // easy-peasy
class MyEvent2 : public EventWrapper<MyEvent2> {};
Note that MyEvent1::staticType() != MyEvent2::staticType(): registerEventType() returns unique types each time it's called.
Now I want the event class to carry some data:
template <typename Derived> class StringEvent : public EventWrapper<D> {
std::string m_str;
public:
explicit StringEvent(const std::string & str) : m_str(str) {}
std::string value() const { return m_str; }
};
But here we run into a problem: we need to manually define the constructor in each of the derived classes. The whole point here is that creation of such classes should be easy, as there may be many different string-carrying event types. But it's anything but easy:
class MyEvent3 : public StringEvent<MyEvent3> {
public: MyEvent3(std::string s) : StringEvent(s) {}
};
This obviously gets old real quick, even with C++11 constructor forwarding:
class MyEvent3 : public StringEvent<MyEvent3> { using StringEvent::StringEvent; };
What we'd want is a way of injecting this constructor into the derived class, or avoiding doing so while still providing for ease of use. Sure you can hide it in a preprocessor macro, but I hate those macros, they are a maintenance pain as they introduce new names for very simple concepts.
We can of course use a dummy type. Note that there's no need for a definition of the dummy type. It's only a name to be used as the type argument.
// Pre-C++11
class DummyEvent3;
typedef StringEvent<DummyEvent3> MyEvent3;
// C++11
class DummyEvent3;
using MyEvent3 = StringEvent<DummyEvent3>;
Another solution would be to use an int template argument and use an enum value, but this brings back the uniqueness issue that got solved by using the registerEventType() in the first place. It'd be no fun to guarantee that a large program is correct. And you'd still need to spell out the enum.
So, I've come up with a metaprogram class that I'll call a metafactory, that can produce the ready-to-use StringEvent classes for us, while keeping it all to one type definition:
// the metafactory for string events
template <typename Derived> class StringEventMF {
public:
class Event : public EventWrapper<Derived> {
std::string m_str;
public:
explicit Event(const std::string & val) : m_str(val) {}
std::string value() const { return m_str; }
};
};
or simply
template <typename Derived> class StringEventMF {
public:
typedef StringEvent<Derived> Event;
};
This is used like:
class Update : public StringEventMF<Update> {};
class Clear : public StringEventMF<Clear> {};
void test() {
Update::Event * ev = new Update::Event("foo");
...
}
The classes you use are Update::Event, Clear::Event. The Update and Clear are metafactories: they generate the desired event class for us. The derivation from the metafactory sidesteps derivation from the concrete class type. The metafactory type gives the unique type discriminator needed to create unique concrete class types.
The questions are:
Is there any "cleaner" or "more desirable" way of doing it? Ideally, the following non-working pseudocode would be my ideal way of doing it - with zero repetition:
class UpdateEvent : public StringEvent <magic>;
The name of the derived class appears only once, and the name of the base concept StringEvent appears only once, too. The CRTP requires the class name to appear twice - so far I think it's acceptable, but my metaprogramming-fu is in tatters. Again, I want a preprocessor-less solution, it'd be a no-brainer otherwise.
Is the name metafactory my original invention (ha ha), or is it merely my google-Fu that's lacking? This metafactory pattern seems to be quite flexible. It's easy to compose metafactories by multiple derivation. Say you wanted an Update::Event made by one factory, and Update::Foo made by another.
This question is motivated by this answer. Note: in real code I'd be using QString, but I'm trying to keep it as generic as possible.
I think what you're looking for might be just using placement new to instantiate the base class.
The derived class won't be constructable because unless they will create a matching constructor.
But, they don't have to be constructable, you could use them anyway. (It could still be destructable).
template <class T>
class Base
{
protected: Base(int blah) { }
public: static T* CreateInstance(int data) {
T* newOjectBlock = reinterpret_cast<T*>(::operator new(sizeof(T))); // allocate enough memory for the derived class
Base* newBasePlace = (Base*)(newOjectBlock); //point to the part that is reseved for the base class
newBasePlace= new ((char*)newBasePlace) Base(data); //call the placement new constrcutor for the base class
return newOjectBlock;
}
};
class Derived : public Base<Derived> {}
Then let the CRTP base class construct the derived class like this:
Derived* blah = Derived::CreateInstance(666);
If anyone ever wants to initialize the derived class, they should either make a matching constructor that calls the base class constructor.
OR, just make an .init() method that initiates its members, and will be called after the instance is created.
OR, we can think of something else, this is just an idea of a concept.
Yochai Timmer has come up with an alternative way of approaching the problem. Instead of having to forward the constructor from the data carrier class, he exposes a factory method that produces pseudo-derived classes. As it invokes undefined behavior, I'm not particularly keen on it.
Expanding a bit on the original metafactory concept, it's possible to make generic metafactory that can be used to make unique event types that wrap "any" data-carrying class.
The approach for C++11 uses constructor forwarding so that plain non-template data carrier classes can be used. The approach for C++98 requires a templated data carrier class and, internally, a bit more gymnastics, but it works as well.
The event classes can't be further derived from. This is necessary since the derived classes would all share the value of staticType, and that can't be allowed, as DyP duly noted in the comments.
To test the code, you need the event wrapper, the metafactory and data carrier selected for your variant of C++, and the test/usage part.
The Event Wrapper (Common Code)
In either case, our basic event wrapper CRTP class that generates a unique static type value for the event is:
// A type-identifier-generating wrapper for events. It also works with RTTI disabled.
template <typename Derived> class EventWrapper : public QEvent {
public:
EventWrapper() : QEvent(staticType()) {}
static QEvent::Type staticType() {
static QEvent::Type type = static_cast<QEvent::Type>(registerEventType());
return type;
}
static bool is(const QEvent * ev) { return ev->type() == staticType(); }
static Derived* cast(QEvent * ev) { return is(ev) ? static_cast<Derived*>(ev) : 0; }
};
Note that it also provides a cast-to-derived method. You'd use it in an event handler, given a pointer to a base event class:
void MyClass::customEvent(QEvent* event) {
if (MyEvent::is(event)) {
auto myEvent = MyEvent::cast(event);
// use myEvent to access data carrying members etc)
}
}
The C++98 Metafactory
The Carrier is a parametrized data carrier class, such as StringData below.
// The generic event metafactory
template <typename Derived, template <typename> class Carrier> class EventMF {
class EventFwd;
class Final;
class FinalWrapper : public EventWrapper<EventFwd>, public virtual Final {};
public:
// EventFwd is a class derived from Event. The EventWrapper's cast()
// will cast to a covariant return type - the derived class. That's OK.
typedef Carrier<FinalWrapper> Event;
private:
class EventFwd : public Event {};
class Final {
friend class FinalWrapper;
friend class Carrier<FinalWrapper>;
private:
Final() {}
Final(const Final &) {}
};
};
The EventFwd class is needed so that we have something sane to pass to the EventWrapper template as the derived class, so that the cast() static method will work. The FinalWrapper is there since in pre-C++11 we can't friend typecasts.
Now for the parametrized data carrier. It'd be the same as for the C++11 variant below except for needing to have a parametrized base class.
// A string carrier
template <typename Base> class StringData : public Base {
QString m_str;
public:
explicit StringData(const QString & str) : m_str(str) {}
QString value() const { return m_str; }
};
The C++11 MetaFactory
// The generic metafactory for unique event types that carry data
template <typename Derived, class Data> class EventMF {
class Final;
EventMF();
EventMF(const EventMF &);
~EventMF();
public:
class Event : public EventWrapper<Event>, public Data, private virtual Final {
public:
template<typename... Args>
Event(Args&&... args): Data(std::forward<Args>(args)...) {}
};
private:
class Final {
friend class Event;
private:
Final() {}
Final(const Final &) {}
};
};
The gymanstics with forward-declaration of the Final class are there since forward-declaring the Event class is more typing.
The data carrier is as simple as it gets:
// A string carrier
class StringData {
QString m_str;
public:
explicit StringData(const QString & str) : m_str(str) {}
QString value() const { return m_str; }
};
Usage & Tests (Common Code)
And now we can use the generic metafactory to make some concrete metafactories, and then to make the event classes we need. We create two unique event types that carry the data. Those event classes have unique staticType()s.
// A string event metafactory
template <typename Derived> class StringEventMF : public EventMF<Derived, StringData> {};
class Update : public EventMF<Update, StringData> {}; // using generic metafactory
class Clear : public StringEventMF<Clear> {}; // using specific metafactory
#if 0
// This should fail at compile time as such derivation would produce classes with
// duplicate event types. That's what the Final class was for in the matafactory.
class Error : public Update::Event { Error() : Update::Event("") {} };
#endif
int main(int, char**)
{
// Test that it works as expected.
Update::Event update("update");
Clear::Event clear("clear");
Q_ASSERT(Update::Event::staticType() != Clear::Event::staticType());
Q_ASSERT(Update::Event::staticType() == Update::Event::cast(&update)->staticType());
qDebug() << Update::Event::cast(&update)->value();
Q_ASSERT(Update::Event::cast(&clear) == 0);
qDebug() << Clear::Event::cast(&clear)->value();
Q_ASSERT(Clear::Event::cast(&update) == 0);
}

Add subclasses of templated base-class to container without super-base-class?

I'm trying to create a vector (or any STL container, really) that could hold a set of various objects that are subclasses of one specific type. The problem is that my base class is templated.
From what I can tell, I have to create an interface/abstract super base class (not sure what the preferred C++ terminology is). I'd prefer not to do this, and just use my (templated) abstract base class. Below is some example code.
Basically, is there a way not to require the WidgetInterface? Someway to tell the compiler to ignore template requirements? If I must have WidgetInterface, am I going the right way with the following?
#include <vector>
#include "stdio.h"
enum SomeEnum{
LOW = 0,
HIGH = 112358
};
// Would like to remove this WidgetInterface
class WidgetInterface{
public:
// have to define this so we can call it while iterating
// (would remove from Widget if ended up using this SuperWidget
// non-template baseclass method)
virtual void method() = 0;
};
template <class TDataType>
class AbstractWidget : public WidgetInterface{
public:
TDataType mData;
virtual void method() = 0;
// ... bunch of helper methods etc
};
class EnumWidget : public AbstractWidget<SomeEnum>{
public:
EnumWidget(){
mData = HIGH;
}
void method(){
printf("%d\n", mData); // sprintf for simplicity
}
};
class IntWidget : public AbstractWidget<int>{
public:
IntWidget(){
mData = -1;
}
void method(){
printf("%d\n", mData); // sprintf for simplicity
}
};
int main(){
// this compiles but isn't a workable solution, not generic enough
std::vector< AbstractWidget<int>* > widgets1;
// only way to do store abitary subclasses?
std::vector<WidgetInterface*> widgets2;
widgets2.push_back(new EnumWidget());
widgets2.push_back(new IntWidget());
for(std::vector<WidgetInterface*>::iterator iter = widgets2.begin();
iter != widgets2.end(); iter++){
(*iter)->method();
}
// This is what i'd _like_ to do, without needing WidgetInterface
// std::vector< AbstractWidget* > widgets3;
return 0;
}
No, you can't use directly AbstractWidget as a parameter of STL container or anything else.
The reason is that class AbstractWidget does not exist. It is only a template for compiler to construct classes from.
What exists is AbstractWidget<SomeEnum> and AbstractWidget<int> only because of EnumWidget and IntWidget inheriting from them.
Templates exist at compiler-level only. If AbstractWidget<T> weren't used anywhere in your code, there would be no traces of it during the runtime.
Therefore, the code you posted seems to be the best (if not only) solution for your problem.
What you've done is the solution: you need a common class/interface, and since AbstractWidget is class template, therefore it cannot be used as common class for all concrete classes for which the template argument is different. So I think, you should go with this class design. It seems to be quite reasonable solution.
In fact the classes AbstractWidget<int> and AbstractWidget<double> are different classes, so your class IntWidget is a subclass of the first but is in no relation with the second. You need to have a common parent class to put in the vector so unfortunately you can not avoid the common interface that is not templated.
This could be completely in the wrong direction, but could you do something like this:
template <class T>
class ConcreteWidget : public AbstractWidget<T>
{
};
and then use template specialization to define your specific widgets like this:
template <>
class ConcreteWidget : public AbstractWidget<int>
{
public:
ConcreteWidget() : mData(-1) {}
};
template <>
class ConcreteWidget : public AbstractWidget<SomeEnum>
{
public:
ConcreteWidget() : mData(HIGH) {}
};
So rather than having an IntWidget and an EnumWidget, you'd have a ConcreteWidget and ConcreteWidget and then could simply have a vector<WidgetInterface> that would be the super of all of these generic children?
I'm not sure if this solves your problem, or would even work. I'd love feedback on this answer.