C++ templates: Calling member function of derived template class from base class - c++

I'm currently working on a spreadsheet application, but I'm having problems with templates.
Every cell of the template can contain a variable which can be any of the standard types.
The relevant class is SpreadSheet, whose most important member variable is SheetCells, which has
type vector< vector<CellBase*> >. The CellBase class is an abstract class from which CellField<T> is
derived, the latter being the template class storing one piece of data corresponding to exactly one cell
of the spreadsheet.
I have another class, SheetView, that eventually has to display the spreadsheet. (To keep things simple,
assume that this class has full access to every other class.) This class doesn't really care what type
the value of every cell is, as it will convert everything to a string anyway. However, my problem is writing
a member function of SpreadSheet that returns a string, containing the data. My first idea was to write a function
std::string SpreadSheet::getDataFromSheet(int row, int column) that SheetView would call, and then that function would do
return (std::to_string(SheetCells[row][column] -> getData())), where getData() is a member function of CellField<T>, returing
something of type T.
However, since SheetCells contains pointers to CellBase classes, I must make getData a member of CellBase,
but this is not possible, since I want getData() to return a variable of type T, the same type as the template class
CellField.
The relevant parts of all class definitions are found below.
//SpreadSheet
class Spreadsheet
{
private:
int _height, _width;
public:
Spreadsheet(int newHeight, int newWidth);
~Spreadsheet();
string getData(int row, int column);
vector< vector<CellBase*> > SheetCells;
};
//CellBase
class CellBase
{
public:
CellBase();
virtual ~CellBase();
};
//CellField
template<typename T>
class CellField : public CellBase
{
public:
CellField(T newValue);
virtual ~CellField();
T getData();
T _value;
};
So in short, I want to be able to call getData() from SpreadSheet, but the member variables of the latter
only contain pointers to CellBase classes (but the classes are actually of type CellField<T>).
I've looked at similar questions, but none of them seem to address the issue of a base class member function calling a template class<T> function where the latter and the former need to return a variable of type T. Maybe void* pointers will work?

As C++ is a strongly typed language, you can't call them directly this way, since the compiler would not be able to figure out what the return value of the function is.
What you need to do is, map it all to a common interface. The question you should ask is: what are the information i realy need from the CelField? Maybe all you need is the string-representation of the value, then you could do something like this:
class CellBase
{
virtual std::string getData()=0;
};
template<typename T>
class CellField : public CellBase
{
std::string getData(){//some implementation}
};
Another option is the use of boost::any, which is able to contain any type you like. This is especially useful if you don't need to actually interfere with the returned value other than passing it to some other function taking "an arbitrary parameter". However in order to really use the value, you still have to cast it to a specific type using boost::any_cast<T>() and therefore need to know which type you expect and do a proper error-handling if the type is wrong.

A possible solution is employ a visitor, along these line:
Class Visitor
{
virtual ~Visitor(void) {}
virtual void visit(CellBase<int> *cell) {}
virtual void visit(CellBase<float> *cell) {}
...
} ;
class CellBase
{
public:
CellBase();
virtual ~CellBase();
virtual void accept(Visitor *v) { v->visit(this) ;}
};
class DataGetterVisitor : public Visitor
{
public:
virtual void visit(CellBase<int> *cell)
{
// here I know how to make the transformation
}
virtual void visit(CellBase<float> *cell) {}
string text ;
} ;
string dataGetter(CellBase *cell)
{
DataGetterVisitor visitor ;
cell->accept(visitor);
return visitor.text ;
}

Related

Database interface using inheritance and templates

I am trying to implement a simple database interface than can handle different types, including custom classes. I wanted to pick inheritance or templates but it seems that I used both with no good results.
Header file
enum class RECORD_TYPE
{
TYPE_LONG = 11,
TYPE_STRING = 12
//other types
};
// the reason I created this class is to use it as function member parent
class RecordType
{
public:
RecordType(RECORD_TYPE record_type) : record_type_(record_type) {}
RECORD_TYPE get_record_type()
{
return record_type_;
}
protected:
RECORD_TYPE record_type_;
};
template<class T>
class RecordType_t : public RecordType
{
public:
RecordType_t(T value, RecordType type) : RecordType(type), value_(value) {}
const T &get_value() const { return value_; }
protected:
T value_;
};
class RecordType_long : public RecordType_t<long>
{
public:
RecordType_long(long value) : RecordType_t(value, RECORD_TYPE::TYPE_LONG) {};
};
class RecordType_string : public RecordType_t<std::string>
{
public:
RecordType_string(std::string value) : RecordType_t(value, RECORD_TYPE::TYPE_STRING) {};
};
Usage
void add_record(const RecordType &record)
{
//here I need to know the type(string/long/custom) because the types have to be stored different
switch (record.get_record_type())
{
case RECORD_TYPE::TYPE_LONG:
//long x = record.get_value();
case RECORD_TYPE::TYPE_STRING:
//string x = record.get_value();
//then do something with these values
};
};
Database db;
RecordType_string str("test");
db.add_record(str);
RecordType_long lng(200);
db.add_record(lng)
My main problem (apart from the fact that I am pretty sure it's bad design) is that in the function add() I don't have access to get_value() member function so I can get the values of each type. Because, of course, in the parent class, if I create the get_value(), I won't know what type to return.
Can you suggest how to implement better this thing?
Thank you
P.S. I could dynamically cast from RecordType into RecordType_long/RecordType_string/etc but I read here that this is really really bad design.:)
The problem is that templates provide a polymorphic behavior which is orthogonal to the one provided by inheritance.
The former provides parametric polimorphism while the latter provides subtyping.
These two different types of polymorphism doesn't mix together in C++. Each template specialization is a different type which is orthogonal to the others specialization of the same template, which means that there is no is-a relationship between such types as you have with inheritance.
So your choices really depend on the design you intend to use. To let each kind of field save itself on the database for example you would need to let each instance manage its own serialization without the need of knowing which is who, for example:
class SerializableRecord
{
public:
virtual void save(Database& db) const;
}
class RecordType_long : private RecordType_t<long>, public SerializableRecord
{
public:
void save(Database& db) const override {
long value = get_value();
/* save it on database somehow */
}
}
In this way you can use polymorphism and templates together but for two different purposes, without the need of knowing which specific kind of record you are going to save, of course this also implies that you need to work with pointers or object slicing occurs.
Another solution would be to make Database::save templated and specialize for various types:
class Database {
public:
template<typename T> void save(const T& record);
}
template<> void Database::save<RecordType_t<long>>(const RecordType_t<long>& record) {
long value = record.get_value();
// ...
}
Actually you have many options, it really depends what you need to achieve and the complexity of the structure itself.

Derived class template

I have some question on derived class templates. I have base and derived class templates like this:
// This is base class
class CParameter {
public:
CParameter(std::string name) : name(name) {}
// virtual ~CParameter() {} // deleted for good design:)
public:
std::string name;
};
...
// This is derived class
template <typename T>
class CTemplateParameter : public CParameter {
public:
CTemplateParameter(std::string name) : CParameter(name) {}
public:
T parameter;
};
and I declare some type parameters the push them to base class vector
//Base class parameters
std::vector<CParameter*> parameters; // !
CTemplateParameter<CMatrix4<float>> mat4;
CTemplateParameter<CVector3<float>> vec3;
CTemplateParameter<float> flt;
parameters.push_back(mat4);
parameters.push_back(vec3);
parameters.push_back(flt);
I have template SetParameter function:
// This method moved to CParameter base class
template <typename T>
bool SetParameter(const CTemplateParameter<T>& param) {
// switch(typeof(T)) {
// set parameter
if (std::is_same<T, int>::value)
// gLUniform1i(...)
else if (std::is_same<T, CMatrix4<float>>::value)
// glUniformMatrix4fv(..)
...
}
So my questions:
1) How to set all parameter individual?
// Notice this function is not template
void SetAll() {
for each parameter
SetParameter(parameter[i])
}
2) Without enum, can I get type of parameter and create a type in run time? Like:
Pseudo code:
//get type of parameter[i]
//create a parameter from
T type = GetTypeofParameter(parameter[i]);
CTemplateParameter<type> newType;
3) Can i get a derived class type like this or how to cast?
CTemplateParameter<void*>* p = dynamic_cast<CTemplateParameter<void*>>(parameters[i]);
Thanks so much.
My comments seem to have pushed ADesignersEncyclopedia away from a template/virtual mix but not toward a practical alternative. The original question doesn't give enough info to decide whether there is a practical alternative. Lacking such a practical alternative, do the virtual/template mix correctly (with CRTP) rather than reject it entirely:
In your target class, you want setParameter in two forms, neither of which is a template. The first form dispatches to the setParameter inside the parameter class, which dispatches back to the second form in the target class:
bool SetParameter(const CParameter& param) {
return param.SetParameter( *this );
}
The second form is overloaded on the value type:
bool SetParameter(int value) {
// whatever
}
bool SetParameter(CMatrix4<float> const& value) {
// whatever
}
...
In your parameter base class, you want SetParameter pure virtual
class CParameter
{
...
virtual bool SetParameter( TargetType& ) const = 0;
...
};
Then you need a CRTP base class, which should be derived from your simple base class:
template<class ActualType>
class CRTPParameter : public CParameter
{
CRTPParameter(std::string name) : CParameter(name) {}
ActualType* This() {return static_cast<ActualType*>(this); }
ActualType const* This() const {return static_cast<ActualType const*>(this); }
// various things including
ActualType* clone() const { return new ActualType( *This() ); }
bool SetParameter( TargetType& target ) const
{ return target.SetParameter( This()->parameter ); }
};
Then your template class derives from your CRTP class
template <typename T>
class CTemplateParameter : public CRTPParameter<CTemplateParameter<T> > {
public:
typedef CRTPParameter<CTemplateParameter<T> super;
CTemplateParameter(std::string name) : super(name) {}
If everything else is simple enough, then the whole CRTP scheme might be overkill and you could just move clone and SetParameter from CRTPParameter to CTemplateParameter and go back to not having CRTPParameter.
But in my experience with such structures, things soon get messy in CTemplateParameter in ways that a best dealt with by the extra layer.
1/
You should define setParameter in Cparameter as an abstract method, and implement it in your template class.
2/
I suggest to use a clone(or a factory) method, defined as I suggested in 1/. In this method you can copy(or create) your object then define it.
3/
No. You can't cast CtemplateParameter<float> to CtemplateParameter<void*>
1) How to set all parameter individual?
You can't iterate and set the value for all of them, unless you know the type. And put a huge amount of dynamic_cast would not be the solution either as it is not scalable.
One solution would be to keep a map of std::function. These function would not take any parameter and return nothing. They will set the parameter with the right values. Pushing into the vector would be like this:
std::map<CParameter*, std::function<void()>> mySets;
// ...
mySets.emplace(&parameter, [ObjectThatGiveMeNext, &parameter]() {
parameter.setParameter(ObjectThatGiveMeNext.get());
});
Even if you contain the parameter, it is not your main container for parameters. It is only to keep track of which parameter is associated to which function.
The ideal would be to create this function when you create the parameter, because you know the type of the parameter there.
Another solution would be to create a virtual function updateValue that would call setParameter with this.
2) Without enum, can I get type of parameter and create a type in run time?
That is not really possible it's a context where you don't know the type, so you must either know the type (a switch case) or rely on polymorphic behaviour. I think the best here is to rely on polymorphic behaviour.
I would add a virtual function clone for that. Maybe not the famous straight clone function, but a clone function that return both the parameter and the function to set it's value. Something a bit like that:
std::tuple<std::unique_ptr<CParameter>, std::function<void()>> clone();
Consider a typedef or using in this case as the type is loooooong.
3) Can i get a derived class type like this or how to cast?
No you can't. You would need to convert the instance of your class to another, not related type. I would not do that. Instead, keep your code that deal with your specific derived class where you explicitely know the type and keep the generic code generic (eg: not trying to know the type). This is the best advice I can tell you right now.

C++11 Pure virtual 'templated' return type in non-templated base class

Here's what I'm trying to accomplish:
I'm trying to created a linked list of various types. In order to accomplish this, I figured polymorphism would be a great way to go about.
I have two classes, AttributeBase and Attribute. AttributeBase is used by AttributeSet, which just stores the start and end points of the linked list of Attribute<T>'s (as AttributeBase*'s) and does modification on the list. AttributeBase is a base class of Attribute<T> that is only in the design for the sake of making generic pointers. Attribute<T>, of course, is the specific type of AttributeBase where the actual value is stored. The main data of each Attribute<T> is an inherited string (the attribute's name, or 'key' if you will) and a value of type T.
So, thus far I have (simplified):
class AttributeBase
{
public:
AttributeBase() = delete;
AttributeBase* GetNext() { return next; };
AttributeBase* GetPrev() { return prev; };
std::string GetName() { return name; };
//Sometimes I need to get/set the value stored in a derived class
//But, how would I define the function here since the return
//type is of type T as defined in Attribute?
virtual ???? GetValue = 0;
virtual void SetValue(????) = 0;
friend class AttributeSet;
private:
AttributeBase* next = nullptr;
AttributeBase* prev = nullptr;
std::string name;
};
template <class T>
class Attribute : public AttributeBase
{
public:
Attribute( std::string _name, T _value ){ name = _name; value = _value };
T GetValue(){ return value; };
void Setvalue(T){ value = T; };
private:
T value;
};
class AttributeSet
{
public:
template <class T>
void Add(std::string,T); //Add an Attribute<T>(std::string,T) to the list
void Delete(std::string);
bool Contains(std::string _name); //Scan the list to determine if an
//attribute with name of _name exists
template <class T>
T Get(std::string); //Scan the list for 'name' and return
//AttributeBase*->GetValue()
private:
AttributeBase* start = nullptr;
AttributeBase* end = nullptr;
}
Since I tried to keep AttributeBase generic and non-templated (to avoid strongly-typed start and end pointers in AttributeSet), this brings up a problem. How do I specify an as-of-yet unspecified return type for the virtual function BaseAttribute::GetValue(). I first tried using auto, got a compile error.
Being as no instances of AttributeBase are ever actually created (and the default constructor deleted) I figured it would be possible to leave out GetValue and define it in the derived class. However, if I try *AttributeBase->GetValue() it errors out since GetValue() isn't defined in AttributeBase, only the subclasses. You would think the compiler would know that the pointer has to point to a derived class (the only derived type) since AttributeBase cannot be directly constructed.
So, in order to use GetValue() I have to know the type of the previous value ahead of time to be able to cast the AttributeBase* to an Attribute*. This would be trivial if AttributeBase itself were templated and contained a value T type. I could then just access AttributeBase*->type to determine the type of pointer I need to cast. However, like I said, templating AttributeBase destroys the intended use of the object.
More than likely, I'm going about this in a completely wrong way (yet again). But at this point I am stuck for ideas. Any help would be appreciated!
So a truly general solution doesn't exist. You just can't get any arbitrary type from a base class because all your overrides of your base class virtual function have to have the same return type.
That leaves you two options.
First, you can decide in advance that you're going to have your list hold any object that derives from some common base type. This will severely limit what you can put into your list, but at least you have full freedom with those objects once they're there.
Second, depending on what you want to actually do with the objects once they're in your list, you can look at the new Boost.TypeErasure library. If all you need to do with list is, say, output them all, or some either small amount of operations, this can help you get there.
Since the signatures of GetValue and SetValue depend on a type, they need to be templates. But they can be template members without requiring a class template.
class AttributeBase
{
public:
template <typename T> T GetValue() const;
template <typename T> void SetValue(T);
//...
};
template <typename T>
T AttributeBase::GetValue() const
{
return dynamic_cast<Attribute<T>&>(*this).GetValue();
}
template <typename T>
void AttributeBase::SetValue(T val)
{
dynamic_cast<Attribute<T>&>(*this).SetValue(val);
}
template <typename T>
T AttributeSet::Get(std::string const& name) const
{
// (assuming a private helper method Find().)
const AttributeBase* attr = Find(name);
if ( !attr )
throw std::invalid_argument("attribute not in set");
return attr->GetValue<T>();
}
One gotcha, though: these functions will all throw an exception if you happen to use the wrong type. And SetValue might automatically deduce its template argument, and might do so incorrectly. For example, if a is a AttributeBase& reference which is really an Attribute<long int>, then a.SetValue(1) is the same as a.SetValue<int>(1), which will throw. The correct expression would be a.SetValue<long int>(1) (or a.SetValue(1L), but I'd prefer the explicit template argument).

C++ polymorphic functions with differing return types

I am creating a property class which stores a unique key and an arbitrary value as strings (plus an optional comment string for use when writing to configuration files). Currently I'm using the method of creating a base property class which holds the raw strings, and then subclassing this into type-specific properties - eg. an IntProperty which implements a getValue() function that converts the string to an int - to avoid having to convert a property value manually from a string every time I want to read it. These subclasses use getPropertyType(), a virtual function defined in the base and overridden in each of the derived, to return an enum value to identify which type of property they hold, and the base class returns a "none" identifier.
(As a side note, I shied away from templates because I'm using Qt and its required interface macro doesn't support templated objects. If it's worth using templates I may ditch the idea of using interfaces.)
My intention was to allow for lists of multiple different types of properties (string, int, float...) by subclassing them from the base property class and allowing arrays of base property pointers. However, I run into the problem that it then becomes very awkward to extract the property as a specific type from one of the derived classes, since the pointer to the base class obviously does not know about the newly defined getValue functions in the derived classes. I am left with either the option of extracting the string from the base class and converting manually or by casting the base class pointer to the correct derived class pointer. The first option renders the subclassing useless by requiring that I do the conversion manually, and the second sounds like a nightmare to code since there'll be a large switch statement involved on the property identifier value each time I want to work out which pointer to cast to.
What would be the most intelligent way of going about this problem? I want to keep the retrieval of property values as simple as possible - ie. have as little boilerplate code as I can to go from getting a base class pointer from an array to holding a properly typed copy of the property's value. Would it be worth considering the problem the other way around - have multiple strongly-typed property classes which all support getting and setting their respective value using a string?
What about this? (Untested, but you should get the idea)
class BaseType {
public:
virtual void getValue(string &s) { s = ""; };
virtual void getValue(int &i) { i = 0; };
virtual void getValue(double &d) { d = 0.0; };
};
class IntType : public BaseType {
public:
virtual void getValue(string &s) { s = to_string(myvalue); };
virtual void getValue(int &i) { i = myvalue; };
virtual void getValue(double &d) { d = static_cast<double>(myvalue); };
private:
int myvalue;
};
class DblType : public BaseType {
public:
virtual void getValue(string &s) { s = to_string(myvalue); };
virtual void getValue(int &i) { i = static_cast<int>myvalue; };
virtual void getValue(double &d) { d = myvalue; };
private:
double myvalue;
};
class StrType : public BaseType {
public:
virtual void getValue(string &s) { s = myvalue; };
virtual void getValue(int &i) { i = stoi(myvalue); };
virtual void getValue(double &d) { d = stod(myvalue); };
private:
string myvalue;
};
Surely, since the receiving side needs to know what type it's getting, using a name that indicates what you get back, e.g.
int GetInt(const string& key);
string GetString(const string& key);
double GetDouble(const string& key);
etc. would be just as good as calling it Get(const string& key) - and since the C++ language doesn't allow you to ONLY differentiate on the return type, that wouldn't work.
Another alternative is of course to have a
template <typename T>
void Get(const string& key, T& value);
(May need to actually implement all the different variant's differently, so it may not really help much to use a template, but it's much easier for me to write in an answer as a template! ;) )

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.