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(¶meter, [ObjectThatGiveMeNext, ¶meter]() {
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.
Related
I'm not sure what I am asking for is possible.
I have a templated class called Controller. This is a variadic template class which takes multiple classes and can set their values as such.
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32);
This takes a bunch of different classes together and allows me to to set their values at the same time. setValues is a templated function which allows any type to be passed in. However, right now I am trying to modify my class so that I can set a value within the controller itself for easy retrieval. However this is the part that is proving difficult.
template<typename...Classes>
class Controller
{
public:
Controller(Classes&...objects) : objects(objects...){}
Controller(std::tuple<Classes&...> tup) : objects(tup){}
template<typename T>
void setValues(T value)
{
std::apply([&](auto&...x) { x.updateValue(value),...);}, objects); //calls the updateValue function for each class
}
private:
std::tuple<Classes&...> objects;
};
I want to add the following as a private variable T controllerValue; However, I know that I cannot simply declare T because we cannot define member templates and the compiler has no idea what to expect. Which then I tried to create a private struct:
template<typename T>
struct ControllerValue { T value; };
However, I cannot define a struct underneath that, because the same problem occurs. The compiler has no idea what type ControllerValue is. What I would like is something like this:
template<typename...Classes>
class Controller
{
public:
Controller(Classes&...objects) : objects(objects...){}
Controller(std::tuple<Classes&...> tup) : objects(tup){}
template<typename T>
void setValues(T value)
{
thisValue.value = value;
std::apply([&](auto&...x) { x.updateValue(value),...);}, objects); //calls the updateValue function for each class
}
template<typename T>
T getValue() const { return thisValue.value }
private:
std::tuple<Classes&...> objects;
template<typename T>
struct ControllerValue { T value; };
ControllerValue thisValue;
};
This will not compile at all for the same reason that the compiler has no idea what type ControllerValue should be. And this is where I am stuck. Is this even possible to do? If not, what is another way that I can make this work?
To clear up confusion, the use case would be something like this:
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32);
int commonValue = myController->getValue();
or
Controller<ClassA,ClassB,ClassC>* myController = new Controller<ClassA,ClassB,ClassC>(*a,*b,*c);
myController->setValues(32.3);
double commonValue = myController->getValue();
I think solving this exact problem is impossible in C++ (and still very cumbersome in languages with runtime generics). You can very easily create a polymorphic class that can only store any value:
class PolymorphicBase
{
public:
virtual ~PolymorphicBase() = default;
};
template <class T>
class PolymorphicObject : public PolymorphicBase
{
T value;
public:
PolymorphicObject(T value) : value(std::move(value))
{
}
};
A member of std::unique_ptr<PolymorphicBase> can sufficiently store any value, but how would such a value be retrieved? Probably the easiest is to expose the reference to PolymorphicBase and use dynamic type checks to see if the type is compatible with something you know, but what if you need the code to work for any type?
This is what lambdas with auto parameters are useful for. However, you would have to be able to pass such a lambda to a method on PolymorphicBase and implement that method in PolymorphicObject. This is impossible, since you cannot override a method template (it needs to be a template to accept a lambda) – that's where the compile-time and runtime parts of C++ clash. And there is simply no type in C++ that represents a function accepting any parameter (and knowing its type), which is a template by itself.
You can partially solve this by making the type of the lambda known to PolymorphicBase:
template <class Retriever>
class PolymorphicBase
{
public:
virtual void retrieve(Retriever func) = 0;
virtual ~PolymorphicBase() = default;
};
template <class Retriever, class T>
class PolymorphicObject : public PolymorphicBase<Retriever>
{
T value;
public:
PolymorphicObject(T value) : value(std::move(value))
{
}
void retrieve(Retriever func) override
{
func(value);
}
};
auto lambda = [](auto arg)
{
std::cout << arg << std::endl;
};
PolymorphicObject<decltype(lambda), int> obj(6);
PolymorphicBase<decltype(lambda)> &ptr = obj;
ptr.retrieve(lambda);
This is useful if you ever have only a single way to retrieve the value.
I don't think this is needed in most cases anyway. Usually you use a fixed set of types as the values, so you can use a variant there, or they all implement a common interface, or (as you've pointed out in the comments) you actually meant to move the type parameter from the method to the class (which allows you to check that all the types actually support the value earlier than originally).
However, I agree that in languages with generics/templates it is somewhat hard to have a method that can actually choose its result type in a generic fashion, without being controlled by outside parameters.
I think I'm already close to the solution but am missing the final step.
I want to call a templated member function where I only have a pointer
to the base class and the type is already predefined, so should not
depend on the actual argument type.
This is what I have:
template <typename T> class TTemplateTest;
class CTemplateTest
{
public :
CTemplateTest(){};
template <typename T> double Process(T atValue)
{
return static_cast<TTemplateTest<T>* >(this)->Process(atValue);
}
};
//------------------------------
template <class T>
class TTemplateTest:public CTemplateTest
{
public :
TTemplateTest() : CTemplateTest(){};
virtual double Process(T atNewValue) {return atNewValue;};
};
//------------------------------
template <class T>
class TTemplateTestInt:public TTemplateTest<T>
{
public :
TTemplateTestInt(){};
virtual double Process(T atNewValue);
};
//------------------------------
template <class T> double TTemplateTestInt<T>::Process(T atNewValue)
{
return atNewValue;
}
CTemplateTest* pTTest = new TTemplateTestInt<int>();
// application code
double d = 5.5;
double r;
r = pTTest->Process(d);
I would like to process the argument as integer in this example,
no matter what type the argument is. It calls the right function
but the value is garbage as the double is interpreted as integer
instead of being converted.
I have looked at other questions (and other sites) but couldn't
find a match or solution, e.g.
calling a template function of a derived class
The solution probably is CRTP but I couldn't figure out how
to use it. The application code should stay like this, the
classes definitions can change. The reason for this code is
that it is generated and used in runtime from some xml
configuration file. So the type is not really known at the
function call.
It would probably help if I could use the defined type, like:
template <typename T> double Process(T atValue)
{
return static_cast<TTemplateTest<T>* >(this)->Process((this::type)atValue);
}
Or prevent the automatic creation of the function using double
so the argument is converted to integer as it would happen on
a non templated function.
Thanks for any help.
Edit: Next solution
Does this look valid? It doesn't need casting and we only need a handful of different basic types for the template so there won't be many redirector functions. And it should still be efficient (without typeinfo and such).
I'm also posting it in case somebody else has a similar problem.
class CTemplateTest
{
public :
CTemplateTest(){};
virtual inline double Process(double adValue)=0;
virtual inline double Process(int aiValue)=0;
};
//------------------------------
template <class T>
class TTemplateTest:public CTemplateTest
{
public :
TTemplateTest() : CTemplateTest(){};
virtual inline double Process(double adValue) {
return ProcessImp((T)adValue);
}
virtual inline double Process(int aiValue) {
return ProcessImpl((T)aiValue);
}
virtual double ProcessImpl(T atNewValue)=0;
};
//------------------------------
template <class T>
class CTemplateTestInt:public TTemplateTest<T>
{
public :
CTemplateTestInt(){};
virtual double ProcessImpl(T atNewValue) {return atNewValue;};
};
This then gives the desired result with
CTemplateTest* pTTest = new TTemplateTestInt<int>();
// application code
double d = 5.5;
double r;
r = pTTest->Process(d);
// -> r = 5
Thanks
Your code looks fairly confusing, both in terms of naming and the logic. I don't know what you want to do, but I can explain why your code will lead to strange behavior, which also indicates there are some fondamental design flaw in your code.
To be simplified, your code has something similar to this:
class A {};
class B : public A {};
class C : public A {};
int main () {
A *a_ptr = new B {};
C *c_ptr = static_cast<C*>(a_ptr);
}
There is no reinterpret_cast, but this code still breaks the type system and will lead to undefined behavior. Because B has nothing to do with C, even if they both derive from A.
Back to your code, in class CTemplateTest, function
template <typename T> double Process(T atValue)
{
return static_cast<TTemplateTest<T>* >(this)->Process(atValue);
}
will obtain type T by template argument deduction, not from any predefined type. Thus pTTest->Process(d) will deduce type T to be double and in that function, static_cast the this pointer to an irrelevant pointer TTemplateTest<double>*. But this pointer is indeed a TTemplateTest<int>*, these two classes have no relation except both deriving from CTemplateTest. So it's just the simplified case.
I don't know how to fix this code...
A few observations:
1) your base class has no virtual function, but your derived classes each have unique, unrelated virtual functions. They do not override anything so are kind of pointless being virtual.
2) The base class doesn't know what type the derived type was instantiated with. When CTemplateTest::Process is called, that T is the argument deduced for the function call, and is unrelated to the T used for the derived type. You're merely casting the object to the template instantiated with the type you were provided, ignoring the type your object actually is. This accounts for the garbage; it's undefined behavior.
3) There is no such thing as a template virtual function. One or the other; take your pick. That's basically what I think you are trying to simulate. You want the same function to take any type of parameter and have it passed, as that type, to the derived type, who knows how to process it its own templated way. I'm not sure of a satisfying way to accomplish this.
One thought is to pre-determine a fixed set of types you will accept and handle them individually, one virtual function per supported type. You may be able to make this a bit more flexible with a template parameter list and use the compiler to generate the functions, but I haven't thought that approach entirely through. :)
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 ;
}
Ok, so basically I have a class in use in another class which, among other things, asks on object to report on its relationship to another object of the same type. Works great. FYI this class represents a protocol. Unfortunately, now I'm trying to decorate the class relationship by adding a class called a Wrapper. The main power of this class is that it can take the first class as an argument (or anything else that does the same).:
template< class InnerInterpreter >
class WrapperInterpreter
{
public:
WrapperInterpreter(const InnerInterpreter &m) : innerMessage(m) {}
...
virtual bool respondsToMessage(const WrapperInterpreter<InnerInterpreter> &) const = 0;
public:
//member
InnerInterpreter innerMessage;
};
What I've concluded for other design reasons is that having this as a base class to a set of wrappers (rather than taking two different protocols as arguments) allows me a combinatorial set of outer and inner protocol classes.
So here's my problem: When I try to subclass WrapperInterpreter<>, and in particular provide an implementation to respondsToMessage(), I end up with a subclass that is able to compare to any class in the WrapperInterpreter heirarchy. But that's not actually what I want to do. What I would like to do is to force the subclass to implement a method thusly:
template< class Inner >
class ConcreteWrapper : WrapperInterpreter<Inner>
{
...
bool respondsToMessage(const ConcreteWrapper<Inner> &);
...
}
One solution I came to immediately was to simply remove it from the interface of WrapperInterpreter and just let the compiler complain about the missing interface method only when in use with the rest of the design.
So my question is: is there any way to put a method in an abstract class's interface, such that the subclass must take an object of the subclass type as a parameter?
Alternatively, am I trying to use inheritance incorrectly? Does anybody have any useful design patterns that might help me to address this problem?
There is a design called CRTP (Curiously Recurring Template Pattern) which consists in passing the type of the Child to the Parent as a template parameter:
template <typename Child>
class WrapperInterpreter {
using Inner = typename Child::Inner; // nested typedef
WrapperInterpreter(Inner const& ...);
virtual bool respondsToMessage(Child const& ...) = 0;
};
template <typename Inner>
class Concrete: public WrapperInterpreter< Concrete<Inner> > {
virtual bool respondsToMessage(Concrete const& ...) override;
};
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).