C++ containers, covariance and template - c++

I have some issues to find a relevant solution to my problem.
I have to return some data from a class, and the type of data kind of depends on the class.
My first solution was this :
class Base
{
virtual QVector<Data*> getData() const = 0;
};
class Derived : public Base
{
virtual QVector<DerviedData*> getData() const = 0;
};
But I know this is impossible, even if DerivedData extends Data, because of invalid covariant return types.
So I came up with another idea which implies template. What I did is I turned the Base class into a template class :
template<class T>
class Base
{
virtual QVector<T*> getData() const = 0;
}
And then I could write a Derivedconstructor like that :
Derived::Derived() : Base<DerivedData>() {}
But know I have another problem. Suppose that I write another class, which has a method taking any Base class in parameters.
void Foo::doSomething(Base* b) {
b->getData();
}
This does not compile and says
invalid use of template-name 'Base' without an argument list
which I understand perfectly.
Supposing that my code will look like that :
DerivedClass1 d1;
DerivedClass2 d2;
DerivedClass3 d3;
this->doSomething(&d1);
this->doSomething(&d2);
this->doSomething(&d3);
What are my solutions here ? May I do something like "templating" the method doSomething ?
this->doSomething<DerivedData>(&d1);
With a protoype like
template<class T>
void doSomething(Base<T>* b);
Is that possible ? Is that a good way of thinking ?
Coming from Java, I used to resolve such problems by using wildcards
abstract List<? extends Data> getData();
But I heard there is stricly speaking no such things in C++ (more or less simulable with such things as std::is_base_of).
Thank you for your time.

You can let Derived::getData() return QVector<Data*>. When you need to use it, find out if the pointers in QVector is to Data or DerivedData, using dynamic_cast or similar method.

Related

Functionality of a pure virtual function with variable return type - workaround/design?

I'm working on a very, very simple data access layer (DAL) featuring two classes: DataTransferObject (DTO) and DataAccessObject (DAO). Both classes are abstract base classes and need to be inherited and modified for a specific use case.
class DataTransferObject {
protected:
//protected constructor to prevent initialization
};
class DataAccessObject {
public:
virtual bool save(DataTransferObject o) = 0;
virtual DataTransferObject* load(int id) = 0;
};
in case of a House class from the business logic layer, the implementation of the DAL classes would read something along these lines:
class Dto_House : public DataTransferObject {
public:
int stories;
string address; //...which are all members of the House class...
Dto_House(House h);
};
class Dao_House : public DataAccessObject {
public:
bool save(Dto_House h) { /*...implement database access, etc...*/ }
Dto_House* load(int id) {/*...implement database access, etc...*/ }
};
EDIT: Of course, the derived classes know about the structure of the House class and the data storage.
Simple, nice, okidoke.
Now I wanted to provide a method toObject() in the DTO class in order to quickly convert the Dto_House into a House object. I then read about the automatic return type deduction in C++14 and tried:
class DataTransferObject {
public:
virtual auto toObject() = 0;
};
But I had to discover: No automatic return type deduction for virtual functions. :(
What are your ideas about implementing a "virtual function with deduced return type" for this specific case? I want a general toObject() function in my DTO "interface".
The only thing that came to my mind was something like:
template <typename T>
class DataTransferObject {
virtual T toObject() = 0;
};
class Dto_House : public DataTransferObject<House> {
public:
int stories;
string address;
House toObject() {return House(stories, address);}
};
EDIT:
A possible use case would be:
House h(3, "231 This Street");
h.doHouseStuff();
//save it
Dto_House dtoSave(h);
Dao_House dao;
dao.save(dtoSave); //even shorter: dao.save(Dto_House(h));
//now load some other house
Dto_House dtoLoad = dao.load(id 2);
h = dtoLoad.toObject();
h.doOtherHouseStuff();
But the house does not know it can be saved and loaded.
Of course, the abstract DAO class may be derived to further refine it for the use with, e.g. Sqlite, XML files or whatever... I just presented the very basic concept.
How about setting an empty abstract class - practically, an interface, then have both of your types implement it and set this as the toObject returning reference type?
class Transferable
{
virtual ~Transferable() = 0;
}
And then:
class DataTransferObject {
public:
//Return a reference of the object.
virtual Transferable& toObject() = 0;
};
Dto_House : public DataTransferObject, Transferable { /*...*/ }
House : public DataTransferObject, Transferable { /*...*/ }
The example above is to get my point.
Even better, you can use the DataTransferObject for this cause as your returning reference type, and no other abstract class:
class DataTransferObject {
public:
virtual DataTransferObject& toObject() = 0;
};
Dto_House : public DataTransferObject { /*...*/ }
House : public DataTransferObject { /*...*/ }
Update: If you want to have the classes separated apart, separating any association between data and operations by convention, you could set the name of the base class on something that represents the data i.e.: Building, Construction etc, and then use it for the reference type in toObject.
You can also have the class manipulating those operations on the API of data manipulation.
In general, you can not have a virtual function returning different types in different subclasses, as this violates the whole concept of statically typed language: if you call DataTransferObject::toObject(), the compiler does not know what type it is going to return until runtime.
And this highlight the main problem of your design: why do you need a base class at all? How are you going to use it? Calling DataTransferObject::toObject(), even if you use some magic to get it work (or use a dynamically typed language), sounds like a bad idea since you can not be sure what the return type is. You will anyway need some casts, or some ifs, etc, to get it working — or you will be using only the functionality common for all such objects (House, Road, etc.) — but then you just need a common base class for all of them.
In fact, there is one exception to the same return type rule: if you return a pointer to a class, you can use the Covariant return type concept: a subclass may override a virtual function to return a subclass of the original return type. If all your "objects" have a common base class, you may use something along the lines of
struct DataTransferObject {
virtual BaseObject* toObject() = 0;
};
struct Dto_House : public DataTransferObject {
virtual House* toObject() { /*...*/ } // assumes that House subclasses BaseObject
};
However, this will still leave the same problem: if all you have in your code is DataTransferObject, even if you (but not the compiler) know it is a Dto_House, you will need some cast, which might be unreliable.
On the other hand, you template solution seems quite good except that you will not be able to explicitly call DataTransferObject::toObject() (unless you know the type of the object), but that's a bad idea as I have explained.
So, I suggest you think on how you are going to actually use the base classes (even write some sample code), and make your choice based on that.

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.

Alternative to using dynamic_cast in C++

I have these classes:
class Field{
public:
int X;
void validate(){
validator->validate(this);
}
void setValidator(Validator* v){
validator = v;
}
private:
Validator* validator;
};
class DerivedField : public Field{
public:
int Y;
}
class Validator {
public:
virtual void validate(Field*); // do something with Field.X
};
class DerivedValidator : public Validator {
virtual void validate(Field*); //do something with DerivedField.Y
};
I want to do this:
DerivedValidator* v = new DerivedValidator();
DerivedField* f = new DerivedFiled();
f->setValidator(v);
f->validate(); // Error, Validator::validate called instead of DerivedValidator::validate
Since It doesnt work, what can I do to avoid this:
class DerivedValidator{
void validate(Field* f){
DerivedField* dv = dynamic_cast<DerivedField*>(f);
// do something with dv.Y
}
};
Thank you.
Edit: Ok, all 'bugs' fixed now.
First, by changing the method signature, you've created a new method that will hide the base class's. You need to have DerivedValidator's validate() method take a Field* parameter only.
Then, once you've added the virtual keyword to your methods, when you pass a DerivedField in, the correct method should be called.
You still won't be able to access the inherited values of DerivedField as you haven't told the base class anything about the derived class. ie, Field knows all about Validator types, but has no clue what a DerivedValidator is. Whatever you want to access in the derived class has to go via the base class signature.
It's good that it doesn't work, since DerivedField doesn't inherit from Field. If you want to hack, you can just use C-style casts.
Rather than creating a parallel class hierarchy for fields and validators, you might be better off with a design something like this:
class Field{
public:
int X;
virtual bool validate(Validator* v){
return (v->isValid(X));
}
}
class DerivedField : public Field{
public:
int Y;
virtual bool validate(Validator* v){
return (v->isValid(X) && v->isValid(Y));
}
}
Each of your derived Validator classes can have different ideas of what is valid and what isn't.
You code is full of small errors. First, your classes son't derive from anything, I assume DerivedField inherits from Field and DerivedValidator from Validator. Second, you need to write validator->validate, as it's a pointer. Third, Field::validate has no argument but you call f->validate(v). If these errors are corrected, then the only thing you got to do is make Validator::validate virtual and use your proposed solution (with the dynamic_cast).
you need to make Validator::validate() virtual.

Can we turn such structure into typed class/function?

So in structure like
struct RenderCastedDataFunctor
{
simpleRendererGraphElement* obj_;
RenderCastedDataFunctor(simpleRendererGraphElement* obj)
: obj_(obj) { }
void operator()(char* castedChar, int castedCharLength)
{
obj_->renderCastedData(castedChar, castedCharLength);
}
};
can we turn simpleRendererGraphElement* into abstract type and make its function name we use in structure (renderCastedData) abstract too?
So I have a function inside charGenerator class
template <typename Function>
void AddSubscriberToGeneratedData(Function f)
I want to pass to it functions from different classes of type void (differentClass::*)(char*, int)
With that structure inside some simpleRendererGraphElement I can subscribe function called renderCastedData to data with
charGenerator->AddSubscriberToGeneratedData(RenderCastedDataFunctor(this));
I want to have a way to be capable to pass abstract class function that takes char* and int to AddSubscriberToGeneratedData. How to do such thing?
can we turn
simpleRendererGraphElement* into
abstract type and make its function
name we use in structure
(renderCastedData) abstract too?
Very very good idea. You should do this. Make the class abstract by making it's functions virtual, and then define a concrete class (deriving from this abstract class) which implements the virtual functions. That would be a better design!
And the rest seems already fine. You don't have to do anything, as you're doing this:
AddSubscriberToGeneratedData(RenderCastedDataFunctor(this));
I suppose, here this represents the pointer to an instance of the concrete class. If so, then that should work!
EDIT:
I understand how good this Idea is but
I do not get how to implement it. that
is why I am asking.
Alright. Here is an example:
class AbstractGraphElement
{
public:
virtual void RenderCastedData(char* castedChar, int castedCharLength) = 0;
};
This is your abstract class, and RenderCastedData is a pure virtual function. Now you need to define a concrete class which must define RenderCastedData function. So here it is:
class SimpleGraphElement : public AbstractGraphElement
{
public:
virtual void RenderCastedData(char* castedChar, int castedCharLength)
{
//function body - define it yourself
}
};
Done!
Now what you need to do is this. Modify RenderCastedDataFunctor as follows:
struct RenderCastedDataFunctor
{
AbstractGraphElement* m_graphElement;
RenderCastedDataFunctor(AbstractGraphElement* graphElement)
: m_graphElement(graphElement) { }
void operator()(char* castedChar, int castedCharLength)
{
m_graphElement->RenderCastedData(castedChar, castedCharLength);
}
};
Then add subscriber,
AbstractGraphElement *pGraphElement = new SimpleGraphElement();
AddSubscriberToGeneratedData(RenderCastedDataFunctor(pGraphElement));
I think it gave your some idea, right? The important point is : use pointer of type AbstractGraphElement but initialize this pointer with SimpleGraphElement. I think, you should read about virtual functions, and runtime polymorphism. That would help you a lot.

C++ dynamic type construction and detection

There was an interesting problem in C++, but it was more about architecture.
There are many (10, 20, 40, etc) classes describing some characteristics (mix-in classes), for example:
struct Base { virtual ~Base() {} };
struct A : virtual public Base { int size; };
struct B : virtual public Base { float x, y; };
struct C : virtual public Base { bool some_bool_state; };
struct D : virtual public Base { string str; }
// ....
The primary module declares and exports a function (for simplicity just function declarations without classes):
// .h file
void operate(Base *pBase);
// .cpp file
void operate(Base *pBase)
{
// ....
}
Any other module can have code like this:
#include "mixing.h"
#include "primary.h"
class obj1_t : public A, public C, public D {};
class obj2_t : public B, public D {};
// ...
void Pass()
{
obj1_t obj1;
obj2_t obj2;
operate(&obj1);
operate(&obj2);
}
The question is how do you know what the real type of a given object in operate() is without using dynamic_cast and any type information in classes (constants, etc)? The operate() function is used with a big array of objects in small time periods and dynamic_cast is too slow for it and I don't want to include constants (enum obj_type { ... }) because this is not the OOP-way.
// module operate.cpp
void some_operate(Base *pBase)
{
processA(pBase);
processB(pBase);
}
void processA(A *pA)
{
}
void processB(B *pB)
{
}
I cannot directly pass a pBase to these functions. And it's impossible to have all possible combinations of classes, because I can add new classes just by including new header files.
One solution that came to mind, in the editor I can use a composite container:
struct CompositeObject
{
vector<Base *pBase> parts;
};
But the editor does not need time optimization and can use dynamic_cast for parts to determine the exact type. In operate() I cannot use this solution.
So, is it possible to avoid using a dynamic_cast and type information to solve this problem? Or maybe I should use another architecture?
The real problem here is about what you are trying to achieve.
Do you want something like:
void operate(A-B& ) { operateA(); operateB(); }
// OR
void operate(A-B& ) { operateAB(); }
That is, do you want to apply an operation on each subcomponent (independently), or do you wish to be able to apply operations depending on the combination of components (much harder).
I'll take the first approach here.
1. Virtual ?
class Base { public: virtual void operate() = 0; };
class A: virtual public Base { public virtual void operate() = 0; };
void A::operate() { ++size; } // yes, it's possible to define a pure virtual
class obj1_t: public A, public B
{
public:
virtual void operate() { A::operate(); B::operate(); }
};
Some more work, for sure. Notably I don't like the repetition much. But that's one call to the _vtable, so it should be one of the fastest solution!
2. Composite Pattern
That would probably be the more natural thing here.
Note that you can perfectly use a template version of the pattern in C++!
template <class T1, class T2, class T3>
class BaseT: public Base, private T1, private T2, private T3
{
public:
void operate() { T1::operate(); T2::operate(); T3::operate(); }
};
class obj1_t: public BaseT<A,B,C> {};
Advantages:
no more need to repeat yourself! write operate once and for all (baring variadic...)
only 1 virtual call, no more virtual inheritance, so even more efficient that before
A, B and C can be of arbitrary type, they should not inherit from Base at all
edit the operate method of A, B and C may be inlined now that it's not virtual
Disadvantage:
Some more work on the framework if you don't have access to variadic templates yet, but it's feasible within a couple dozen of lines.
First thing that comes to mind is asking what you really want to achieve... but then again the second thought is that you can use the visitor pattern. Runtime type information will implicitly be used to determine at what point in the hierarchy is the final overrider of the accept method, but you will not explicitly use that information (your code will not show any dynamic_cast, type_info, constants...)
Then again, my first thought comes back... since you are asking about the appropriateness of the architecture, what is it that you really want to achieve? --without knowledge of the problem you will only find generic answers as this one.
The usual object oriented way would be to have (pure) virtual functions in the base class that are called in operate() and that get overridden in the derived classes to execute code specific to that derived class.
Your problem is that you want to decide what to do based on more than one object's type. Virtual functions do this for one object (the one left of the . or ->) only. Doing so for more than one object is called multiple dispatch (for two objects it's also called double dispatch), and in C++ there's no built-in feature to deal with this.
Look at double dispatch, especially as done in the visitor pattern.