Taking template class as a general argument, without specifying template arguments - c++

I've got a fairly unique situation.
I've got a structure resembling the following code, where a class template inherits from its own template argument, which may be a certain BaseClass, or any of its subclasses.
class BaseClass {
...
virtual void BaseMethod();
};
class DerivedClass {
...
virtual void BaseMethod(); // DerivedClass Overrides some of baseclass's methods
void DerivedMethod(); // And it has a few of its own
};
template <class T>
class ClassTemplate : public T {
...
// Some validation to ensure that this class template extends
// either BaseClass or one of its derived classes
void ValidateTemplate(const BaseClass& c) {}
...
}
The point where this becomes tricky is when I want to take a template class argument that is templated after the baseclass, or one of its subclasses:
void func(ClassTemplate& c) { ... c.BaseMethod(); }
Of course, this doesn't compile as its missing its template arguments. However, I'm looking for a solution that will function like the following, without having to actually specify the following function overloads:
void func(ClassTemplate<BaseClass>& c) { ... c.BaseMethod(); }
void func(ClassTemplate<DerivedClass>& c) { ... c.BaseMethod(); }
On top of that, one of my other classes contains a list of ClassTemplate pointers:
class ClassWithList {
std::list<ClassTemplate<BaseClass>*> l;
...
}
With the above, I want the list l to contain both ClassTemplate<BaseClass> objects, and ClassTemplatE<DerivedClass> objects. This has the same root problem - hoping that the latter could be interpreted as the former, as is the case for most implicit conversions in C++. Is this particular kind of conversion possible to do with templates? Or is there an alternate workaround?
Notes:
In func, none ofDerivedClass's functions are used - just like if I had taken a BaseClass argument, I want to be able to access its public members.
However, it is important that I don't take BaseClass as an argument. This is because I need to access members of the ClassTemplate object, which are unique to ClassTemplate itself.
Additionally, I can't resort to using multiple inheritance (Have DerivedClass subclass both ClassTemplate and BaseClass) as this will result in diamond inheritance, thus creating an inheritance hierarchy too complicated for simple virtual inheritance.

From your description, it sounds like you want a function template:
template <typename T>
void func(ClassTemplate<T>& c) { ... c.BaseMethod(); }
For handling the list case, one option is to have a third class that you use as the interface:
struct ClassTemplateBase {
virtual void doSomething() = 0;
};
template <class T>
class ClassTemplate : public T, public ClassTemplateBase {
// ...
}
then you can have a std::list<ClassTemplateBase *>. This avoids the diamond inheritance issue.

Related

Calling base class method in derived class without specifying base class name

When overriding a C++ virtual method, is there a way to invoke the base class method without specifying the exact base class name, in a similar way that we can do it in C# with the "base" keyword? I am aware that this could be in conflict with multiple inheritance, but I wonder if more modern versions of C++ have introduced such a possibility.
What I want to do is something like this:
class A
{
public:
virtual void paint() {
// draw something common to all subclasses
}
};
class B : public A
{
public:
virtual void paint() override {
BASE::paint();
// draw something specific to class B
}
};
I know that in B::paint() we can call A::paint(), I just want to know if there is a more "generic" way to call the base method without referring explicitly to class A.
Thank you in advance.
Andrea
No, there is no fancy keyword to access to the base class.
As some comments already mentioned, some proposals have been rejected by the standard committee.
Personally, in some contexts, I opt for a typedef/using directive; especially when my hierarchy has templated classes.
For instance:
template <typename T>
class A {};
template <typename U, typename T>
class B : public A<T> {
private:
using Base = A<T>;
public:
void foo() {
// Base::foo();
}
};

C++ inheritance in template parameter

I need to pass template as function argument, but template must accept all inherited objects.
For example:
template <class T>
class Template {
public:
Template() {}
};
// IMPORTANT: must accept all children of "Base"
class Test {
Template<Base> *pointer;
public:
Test(Template<Base> *pointer) {...}
};
main() {
Template<Base> *base = new Template<Base>();
Template<Child1> *child = new Template<Child1>();
Test *test1 = new Test(base); // WORKING
// NEXT LINE IS IMPORTANT:
Test *test2 = new Test(child); // ERROR: no matching function for call to 'Test::Test(Template<Child1>*&)'
}
class Base {...};
class Child1 : public Base {...};
class Child2 : public Base {...};
..
I need the most effective way, how to store template in "Test" class, that will accept all children classes. I have lot's of children classes.
1) Is it possible to make some up casting (static_cast) for Child class in argument? It will be good to use it inside of "Template" or inside of "Test" class. Not, when creating new "Test" object, because there will be lot's of new objects.
2) Or pass argument without template argument Test(Template *pointer) {...}?
Or how to solve it?
The reason that the thing you want to do doesn't work is because template types don't observe inheritance in typename parameters.
Template<Base> *base
and
Template<Child1> *child
are completely different types. Trying to use one in place of the other is like trying to pass an int to a function that has a string parameter.
That said, I believe you have two viable options here.
#1 Make Test a template too
One option would be to make Test a template too:
template <typename T>
class Test {
T *pointer;
public:
Test(T *pointer) {...}
};
This would allow the Test object to work with whatever object was passed to it.
#2 Use an interface
Alternatively, by creating an interface, and implementing that interface in Template, you can pass your interface to the Test class:
/**
* Interface that declares the virtual methods that
* will be used by your Test class.
*/
class ITemplate {
public:
virtual ~ITemplate() {}
// Define your methods here.
virtual void Foo() = 0;
virtual void Bar() = 0;
virtual void Baz() = 0;
}
/**
* Concrete ITemplate implementation.
*/
template <class T>
class Template : public ITemplate {
public:
Template() {}
virtual ~Template() {}
virtual void Foo() override {}
virtual void Bar() override {}
virtual void Baz() override {}
};
class Test {
ITemplate *pointer;
public:
Test(ITemplate *pointer) {...}
};
This has the advantage that you can modify your Template class without affecting your Test class, because the Test class works with ITemplate interfaces instead of concrete objects. The downside of this is that you incur the cost of virtual function lookups, which may be undesirable if you're trying to write extremely efficient code.
1) Is it possible to make some up casting (static_cast) for Child class in argument? It will be good to use it inside of "Template" or inside of "Test" class. Not, when creating new "Test" object, because there will be lot's of new objects.
I don't exactly understand what you're suggesting. It won't be possible to cast an unrelated pointer to another.
2) Or pass argument without template argument
No. Templates can not be function arguments.
What you could do, is make Template<T> implicitly convertible to other instances of Template:
template <class T>
class Template {
public:
// ...
template<class U>
Template(const Template<U>&);
};
Depending on how the converting constructor is implemented, it may impose restrictions on U.
And further, if you were to store a Template<Base> instance within Test instead of a pointer:
class Test {
Template<Base> member;
// ...
};
Then, you could accept the Template<Base> by value (to copy) or by rvalue-reference (to move) to the constructor. A Template<Child> would be implicitly converted to Template<Base>:
class Test {
Template<Base> member;
public:
Test(Template<Base> argument) {/* ... */}
};
This approach is the same as is used to allow implicit up casting of the standard smart pointer types.

can i pass object class that is inherited from template class?

How can i pass object that inherited from template as this to function
please see the GameObj::GameObj constructor
i try to pass the GameObj that is inheriting the BaseGameObject template
but its not valid
template<typename T>
class BaseGameObject
{
public:
BaseGameObject(){};
virtual ~BaseGameObject(){};
static T* create(IImageComponent* imageComponent)
{
}
protected:
IImageComponent* m_IImageComponent;
};
class GameObj :public BaseGameObject<GameObj>
{
public:
GameObj(IImageComponent* imageComponent);
virtual ~GameObj(){};
};
GameObj::GameObj(IImageComponent* imageComponent):m_IImageComponent(imageComponent)
{
m_IImageComponent->update(*this); //HERE IS THE PROBLEM IT ASK ME TO PASS TAMPLATE
}
class GameObjImageCompnent
{
public :
GameObjImageCompnent(const std::string &spritefilename);
virtual void update(BaseGameObject& baseGameObject);
private:
std::string m_spritefilename;
};
GameObjImageCompnent::GameObjImageCompnent(const std::string &spritefilename):
m_spritefilename(spritefilename)
{
;
}
void GameObjImageCompnent::update(BaseGameObject& baseGameObject)
{
baseGameObject.setInitWithSpriteFrameName(m_spritefilename);
}
this link doesn't work for me :
Passing template classes as arguments to methods
BaseGameObject is a template. GameObjImageCompnent::update has a declaration virtual void update(BaseGameObject& baseGameObject);. That's wrong because BaseGameObject is not a type but a template.
Maybe you should change that declaration to: virtual void update(BaseGameObject<GameObj>& baseGameObject);
If you need to be able to call that with different BaseGameObjects, you could make GameObjImageCompnent into a template as well:
template<class T>
class GameObjImageCompnent {
// ...
virtual void update(BaseGameObject<T>& baseGameObject);
If that's not an option, you probably need to inherit BaseGameObject from a non-template base class and and use that as your reference type. If a base class for BaseGameObject is not an option either, you need to rethink your design.
class IGameObject {
public:
virtual ~IGameObject() {}
// any other virtual functions that are needed
};
template<typename T>
class BaseGameObject: public IGameObject {
//...
class GameObjImageCompnent {
// ...
virtual void update(IGameObject& baseGameObject);
You seem to be using CRTP. See the pitfalls section:
One issue with static polymorphism is that without using a general base class like "Shape" from the above example, you cannot store your derived classes heterogeneously as each CRTP base class is a unique type. For this reason, it's likely that you'll want to inherit from a shared base class with a virtual destructor, like the example above.
I think that limitation also applies to passing objects of derived classes to a function through a heterogeneous reference.

Inheriting templated base class methods in a templated subclass in C++ without listing every method

In Java, there is a detailed generic class hierarchy for containers. Java defines interfaces like ICollection<T> which is inherited by ISet<T> which is inherited by IList<T> and implemented by ArrayList<T>. I would like to create a similar hierarchy in a C++ library I am creating.
Using C++ templates however, makes this very cumbersome. For example, say I define an ISet<T>:
template<typename T>
class ISet
{
public:
virtual ~ISet() = 0;
virtual void add(T e) = 0;
virtual size_t size() = 0;
virtual bool isEmpty()
{
return size() == 0;
}
};
Then, if I wanted to make a List<T> which implements ISet<T>, I would have to list in the class definition every method that I wanted to inherit but not override, in order to let me later call it without something messy like alist::ISet<T>->isEmpty():
template<typename T>
class List : public ISet<T>
{
public:
...
void add(T e)
{
...
}
virtual sz size()
{
...
}
using ISet<T>::isEmpty; //well this is annoying
};
I understand the reason for this, and "why doesn't this work the way I expect it to?" has been answered in these qeustions: here and here.
My question is, is there a clean (or even any!) way to achieve this without having to explicitly list every inherited but not overridden method in the base class?
What I would really like would be something I could put in List<T> like:
using ISet<T>::*;
which would make all of the methods in ISet<T> dependent in the class definition of List<T>, and would alias them to List<T>::functionName.
Please tell me there is SOME way to achieve this without having to update every inheriting class's list of using directives each time I change one of my templated interfaces!
Do I have to resort to a preprocessor define of using directives defined along with the interface? Arrrrgghhhh!
This statement is incorrect:
... would have to list in the class definition every method that I
wanted to inherit but not override, in order to let me later call it
without something messy like alist::ISet->isEmpty():
Try to compile following code:
template<class T>
class Base {
public:
virtual void f1();
virtual void f2();
};
template<class T>
class Derived : public Base<T> {
public:
virtual void f1();
};
void foobar()
{
Derived<int> d;
d.f1();
d.f2();
}
If you mean that you want to access base class methods or members on derived class, you can simply do that more explicit way:
template<class T>
class Derived : public Base<T> {
public:
virtual void f1() { this->f2(); }
};
That is not messy and works as you asked, just little bit more explicit (some says it is good idea to always use this-> explicitly).

C++: Design, Function template overriding and lack of polymorphism

Have a base class A, and a derived class B which overrides function template Func:
class A
{
A() {...};
~A() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
class B : public A
{
B() {...}
~B() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
(Note that Func is non-virtual, given the lack of support in C++ for templated virtual functions.)
Now have a mainprog API, class M:
class M
{
M(boost::shared_ptr<A> &pInterfaceInput): pInterface(pInterfaceInput)
{}
template <class T>
Evaluate(const String &sInput, T &tResult)
{
pInterface->Func<T>(sInput, tResult);
}
private:
const boost::shared_ptr<A> pInterface;
};
I want the function Evaluate here to support calls to functions on base class A or any of its derived classes (such as B). This class was written with polymorphism in mind before I re-designed class A and B to have templated functions.
Now the problem here is that if I pass a shared pointer of the base type to the derived type then Func of the base class will be called, not the derived class being pointed to.
How do I get around the lack of dynamic polymorphism here?
I've considered making class M a class template on the shared pointer type and having a static_cast in the constructor to ensure this type is of the base class type (A) or of a derived class.
What's the nicest way to do this? I'd prefer not to modify classes A and B to get around this problem but all suggestions are welcome.
Thanks.
Sounds like a double dispatch problem. Perhaps this would be a good place to implement the visitor pattern?
For example, create a class Evaluator, and for each T a subclass ConcreteEvaluator<T>. Give A and B methods that visit the Evaluator. Something like:
class Evaluator
{
virtual void visit_A(A* object);
virtual void visit_B(B* object);
};
template <typename T>
class ConcreteEvaluator : public Evaluator
{
public:
String* input_reference;
T& result_reference;
ConcreteEvaluator(String& input_reference_,T& result_reference_) :
input_reference(input_reference_),
result_reference(result_reference_) {}
virtual void visit_A(A* object) {
object->Func(input_reference,result_reference);
}
virtual void visit_B(B* object) {
object->Func(input_reference,result_reference);
}
}
class A
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_A(this);}
...
}
class B
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_B(this);}
...
}
For each subclass of A, a new method must be added to ConcreteEvaluator, so that this technique works best if A's class hierarchy is stable. And for each subclass of A, it must have an apply_evaluator function defined properly.
On the other hand, this may be total overkill. For about the same amount of work, you could always just pay the price to update M::Evaluate:
class M
{
...
void Evaluate(const String& sInput, T& tResult)
{
// try to downcast to each subclass of A. Be sure to check
// sub-subclasses first
try
{
dynamic_cast<B*>(pInterface.get())->Func(sInput, tResult);
return;
}
catch (std::bad_cast& ) { }
...
// nothing worked. It must really be an A
pInterface->Func(sInput,tResult);
}
...
};
I've show in the question Templatized Virtual function how to use type erasure to get some of the effects of virtual member function. Depending on what you want to do in Func(), you can use the same technique here.