What's faster: down-cast from virtual base or cross-cast? - c++

This is somewhat hypothetical as I'm not too worried about performance - just wondering which option is actually the fastest/most efficient in general, or if there is no difference whatsoever.
Suppose I have the following code for a visitor template that supports overloading:
#define IMPLEMENT_VISITOR_WITH_SUPERCLASS(superclass) \
typedef superclass visitor_super_t; \
virtual void visit(Visitor& v) { v.visit(*this); }
//-----------------------------------------------------------------------------
// Implementation detail:
// Selective dispatcher for the visitor - required to handle overloading.
//
template <typename T>
struct VisitorDispatch {
static void dispatch(Visitor* v, T* t) { v->visit(*t); }
};
// Specalization for cases where dispatch is not defined
template <> struct VisitorDispatch<void> {
static void dispatch(Visitor* v, void* t) { throw std::bad_cast(""); }
};
//-----------------------------------------------------------------------------
// Derive visitors from this and 'Visitor'.
template <typename T>
class VTarget
{
public:
// Don't really need a virtual dtor.
virtual void dispatch(T& t) = 0;
};
//-----------------------------------------------------------------------------
class Visitor
{
public:
virtual ~Visitor() = 0;
template <typename T>
void visit(T& t) {
typedef VTarget<T> target_t;
target_t* tgt = dynamic_cast<target_t*>(this);
if (tgt) {
tgt->dispatch(t);
}
else {
// Navigate up inhertiance hierarchy.
// requires 'super' to be defined in all classes in hierarchy
// applicable to this visitor.
typedef typename T::visitor_super_t super;
super* s = static_cast<super*>(&t);
VisitorDispatch<super>::dispatch(this, s);
}
}
};
//-----------------------------------------------------------------------------
inline Visitor::~Visitor() {}
This is then used to create generic visitors:
class CommonBase {
IMPLEMENT_VISITOR_WITH_SUPERCLASS(void)
virtual ~CommonBase() = 0;
};
class A : public CommonBase {
IMPLEMENT_VISITOR_WITH_SUPERCLASS(CommonBase)
};
class B : public CommonBase {
IMPLEMENT_VISITOR_WITH_SUPERCLASS(CommonBase)
};
class MyVisitor
: public Visitor
, public VTarget<CommonBase>
, public VTarget<A>
, public VTarget<B>
{
public:
virtual void dispatch(CommonBase& obj);
virtual void dispatch(A& obj);
virtual void dispatch(B& obj);
};
Using the visitor ultimately results in dynamic_cast<>'s from Visitor to VTarget<T>, which is a cross-cast.
The other way this could be implemented is to make Visitor a virtual base of VTarget<T> - MyVisitor would then not need to inherit directly from Visitor anymore.
The dynamic_cast<> in the Visitor::visit code would then result in a down-cast from the virtual base, Visitor.
Is one method faster than the other when performing the casts? Or do you only get a size penalty for having the virtual base?

Well, it looks like the cross-cast method is faster than the virtual base method.
With a visitation that requires 1 fallback to a superclass, over 100000000 iterations, the cross-cast method took 30.2747 seconds, and the virtual base method took 41.3999 - about 37% slower.
With no fallback to an overload for a superclass, the cross-cast was 10.733 seconds and the virtual base 19.9982 (86% slower).
I was more interested to know how the dynamic_cast would operate in either mode, really.

Related

CRTP Parameter for Virtual Method of Class Hierarchy

I am trying to pass a CRTP type parameter to a virtual method. Consequently, the virtual method would need to be a template. However, this is not allowed by C++ (yet?), because it would mean that the size of the vtable -- the common way how compilers implement dynamic dispatch -- is unknown until all sources have been compiled and are being linked. (I found this reasoning during my search on SO.)
In my particular setting, however, there is a finite and known amount of CRTP specializations. Hence, it is possible to define a virtual method overload per specialization and override these in the subclasses. I have prepared a small MWE to demonstrate my situation. Consider the following CRTP hierarchy:
template<typename Actual>
struct CRTPBase
{
using actual_type = Actual;
void foo() { static_cast<actual_type*>(this)->foo(); }
int bar(int i) const { return static_cast<const actual_type*>(this)->bar(i); }
};
struct A : CRTPBase<A>
{
void foo() { /* do something A would do */ }
int bar(int i) const { return i + 1; }
};
struct B : CRTPBase<B>
{
void foo() { /* do something B would do */ }
int bar(int i) const { return i - 1; }
};
Next, I want to define a virtual class hierarchy with a virtual method to handle all specializations of CRTPBase<T>. Because I know the particular specializations, I can do as follows:
struct VirtualBase
{
virtual ~VirtualBase() { }
virtual void accept_crtp(const CRTPBase<A> &o) = 0;
virtual void accept_crtp(const CRTPBase<B> &o) = 0;
};
struct VirtualDerived : VirtualBase
{
void accept_crtp(const CRTPBase<A> &o) override { /* much logic to handle A */ }
void accept_crtp(const CRTPBase<B> &o) override { /* similar logic to handle B */ }
};
Observe that there is one virtual method per specialization of CRTPBase<T>, both in the purely virtual base and in all its derived classes. This overhead easily blows out of proportion with increasing number of specializations of CRTPBase<T> and more derived classes of VirtualBase.
What I would like to do, is roughly the following:
struct VirtualBase
{
virtual ~VirtualBase() { }
template<typename T> virtual void accept_crtp(const CRTPBase<T> &o) = 0;
}
struct VirtualDerived : VirtualBase
{
template<typename T> void accept_crtp(const CRTPBase<T> &o) override {
/* one logic to handle any CRTPBase<T> */
}
};
For the reason mentioned in the beginning, this is not possible. User Mark Essel has faced the same issue in another SO post (in an answer, not a question, though).
The user proposes to declare and define the virtual methods for each specialization, but in the derived classes implement the actual logic in an additional template, non-virtual method and then forward calls from the virtual methods to that template method:
struct VirtualBase
{
virtual ~VirtualBase() { }
virtual void accept_crtp(const CRTPBase<A> &o) = 0;
virtual void accept_crtp(const CRTPBase<B> &o) = 0;
};
struct VirtualDerived : VirtualBase
{
void accept_crtp(const CRTPBase<A> &o) override { accept_any_crtp(o); }
void accept_crtp(const CRTPBase<B> &o) override { accept_any_crtp(o); }
private:
template<typename T>
void accept_any_crtp(const CRTPBase<T> &o) {
/* one logic to handle any CRTPBase<T> */
}
};
While this approach avoids code duplication of the logic to handle the CRTPBase<T> specializations, it still requires explicitly writing one method per specialization in the virtual base and all derived classes.
My question is: How can the implementation overhead be reduced?
I have considered using an X macro of the form
#define CRTP_SPECIALIZATIONS_LIST(X) X(A) X(B) // lists all specializations, here A and B
to generate the methods in the virtual base and derived classes. The problem with that is, if the CRTP hierarchy is defined in CRTP.hpp and the virtual base and derived classes are declared/defined in other source files, then the macro is "being leaked" by the header to all translation units that include it. Is there a more elegant way to solve this? Is there maybe a template way of achieving the same goal, perhaps with a variadic template type?
Your help is appreciated. Kind regards,
Immanuel
As all types are known, you might use std::variant to have a free visitor implementation:
using MyVariant =
std::variant<std::reference_wrapper<const CRTPBase<A>>,
std::reference_wrapper<const CRTPBase<B>>,
// ...
>
struct VirtualBase
{
virtual ~VirtualBase() { }
virtual void accept_crtp(MyVariant) = 0;
};
struct VirtualDerived : VirtualBase
{
void accept_crtp(MyVariant var) override
{
std::visit([/*this*/](const auto& crtp){ /*...*/ }, var);
}
};
If you write a CRTP base with the different accept_crtp() overloads that all delegate to a derived class' method, that derived class' method can be a template. That CRTP base can also be used to implement a virtual base:
// declare virtual interface
struct VirtualBase
{
virtual ~VirtualBase() { }
virtual void accept_crtp(const CRTPBase<A> &o) = 0;
virtual void accept_crtp(const CRTPBase<B> &o) = 0;
};
// implement virtual interface by delegating to derived class generic method
template<typename DerivedType>
struct CRTPDerived : VirtualBase
{
using derived_type = DerivedType;
virtual void accept_crtp(const CRTPBase<A> &o)
{ static_cast<derived_type*>(this)->accept_any_crtp(o); }
virtual void accept_crtp(const CRTPBase<B> &o)
{ static_cast<derived_type*>(this)->accept_any_crtp(o); }
};
// implement generic method
struct VirtualDerived : CRTPDerived<VirtualDerived>
{
private:
template<typename T>
void accept_any_crtp(const CRTPBase<T> &o) {
/* one logic to handle any CRTPBase<T> */
}
};
I have found a convenient solution to my problem. It scales well, meaning that the amount of code grows linearly with the number of virtual methods (rather than having number of virtual methods times number of CRTP classes). Further, my solution resolves the actual type of CRTPBase<T> at compile time; no dynamic dispatch except for the virtual method call. Thanks to Ulrich Eckhardt for pointing me in the right direction with his idea of using CRTP in the class hierarchy of VirtualBase.
I will describe how to solve this for a single method. This process can then be repeated for each method. The idea is to generate a purely virtual method in the VirtualBase for each concrete type of CRTPBase<T> and to generate implementations of these methods in all derived classes. The problem with generating methods at compile time is that templates do not allow us to generate method names. The trick here is to exploit overloading semantics and use a tag type to perform tag dispatching.
Let me explain along the example. Given the CRTP hierarchy (note that i slightly changed it for demonstrational purpose)
template<typename Actual>
struct CRTPBase
{
using actual_type = Actual;
actual_type & actual() { return *static_cast<actual_type*>(this); }
const actual_type & actual() const {
return *static_cast<const actual_type*>(this);
}
void foo() const { actual().foo(); }
int bar(int i) const { return actual().bar(i); }
void baz(float x, float y) { actual().baz(x, y); }
};
struct A : CRTPBase<A>
{
void foo() const { }
int bar(int i) const { return i + 'A'; }
void baz(float x, float y) { }
};
struct B : CRTPBase<B>
{
void foo() const { }
int bar(int i) const { return i + 'B'; }
void baz(float x, float y) { }
};
we want to declare a virtual method bark() in the class hierarchy VirtualBase, that accepts any subclass of CRTPBase<T> as parameter. We create a helper tag type bark_t to enable overload resolution.
struct VirtualBase
{
private:
virtual void operator()(bark_t, const A&) const = 0;
virtual void operator()(bark_t, const B&) const = 0;
public:
template<typename T>
void bark(const T &o) const { operator()(bark_t{}, o); }
};
The template method is generic and calls to the proper operator() thanks to overload resolution. The tag type is used here to select the correct implementation. (We want to support multiple methods, not just bark().)
Next we define an implementation of operator() in the derived classes using CRTP:
template<typename Actual>
struct VirtualCRTP : VirtualBase
{
using actual_type = Actual;
actual_type & actual() { return *static_cast<actual_type*>(this); }
const actual_type & actual() const {
return *static_cast<const actual_type*>(this);
}
void operator()(bark_t{}, const A &o) const override { actual()(bark_t{}, o); }
void operator()(bark_t{}, const B &o) const override { actual()(bark_t{}, o); }
};
Note that the implementation calls to some method operator() of static type Actual. We need to implement this next in the implementations of VirtualBase:
struct VirtualDerivedX : VirtualCRTP<VirtualDerivedX>
{
template<typename T>
void operator()(bark_t, const T &o) { /* generic implementation goes here */ }
};
struct VirtualDerivedY : VirtualCRTP<VirtualDerivedY>
{
template<typename T>
void operator()(bark_t, const T &o) { /* generic implementation goes here */ }
};
At this point you might wonder "What did we gain here?". So far, we need to write one method operator() per actual type of CRTPBase<T>. Only in VirtualBase and VirtualCRTP, but still more than we want to write. The neat thing is, we can now generate methods operator(), both the purely virtual declarations in VirtualBase and the implementation in VirtualCRTP. To do so, I have defined a generic helper class. I put the full code with this helper class and the example on Godbolt.
We can use this helper class to declare new virtual methods that take as first parameter an instance of a list of types, as well as additional parameters. It also takes care of const-ness of the parameters and the methods.
struct bark_t : const_virtual_crtp_helper<bark_t>::
crtp_args<const A&, const B&>::
args<> { };
struct quack_t : virtual_crtp_helper<quack_t>::
crtp_args<const A&, const B&>::
args<int, float> { };
struct roar_t : const_virtual_crtp_helper<roar_t>::
crtp_args<A&, B&>::
args<const std::vector<int>&> { };
/*----- Virtual Class Hierarchy taking CRTP parameter ------------------------*/
struct VirtualBase : bark_t::base_type
, quack_t::base_type
, roar_t::base_type
{
virtual ~VirtualBase() { }
/* Declare generic `bark()`. */
using bark_t::base_type::operator();
template<typename T>
void bark(const T &o) const { operator()(bark_t{}, o); }
/* Declare generic `quack()`. */
using quack_t::base_type::operator();
template<typename T>
void quack(const T &o, int i, float f) { operator()(quack_t{}, o, i, f); }
/* Declare generic `roar()`. */
using roar_t::base_type::operator();
template<typename T>
void roar(T &o, const std::vector<int> &v) const { operator()(roar_t{}, o, v); }
};
template<typename Actual>
struct VirtualCRTP : VirtualBase
, bark_t::derived_type<Actual>
, quack_t::derived_type<Actual>
, roar_t::derived_type<Actual>
{ };
struct VirtualDerivedX : VirtualCRTP<VirtualDerivedX>
{
private:
/* Implement generic `bark()`. */
friend const_virtual_crtp_helper<bark_t>;
template<typename T>
void operator()(bark_t, const T&) const { /* generic bark() goes here */ }
/* Implement generic `quack()`. */
friend virtual_crtp_helper<quack_t>;
template<typename T>
void operator()(quack_t, const T&, int, float) { /* generic quack() goes here */ }
/* Implement generic `roar()`. */
friend const_virtual_crtp_helper<roar_t>;
template<typename T>
void operator()(roar_t, T&, const std::vector<int>&) const { /* generic roar() goes here */ }
};
struct VirtualDerivedY : VirtualCRTP<VirtualDerivedY>
{
private:
/* Implement generic `bark()`. */
friend const_virtual_crtp_helper<bark_t>;
template<typename T>
void operator()(bark_t, const T&) const { /* generic bark() goes here */ }
/* Implement generic `quack()`. */
friend virtual_crtp_helper<quack_t>;
template<typename T>
void operator()(quack_t, const T&, int, float) { /* generic quack() goes here */ }
/* Implement generic `roar()`. */
friend const_virtual_crtp_helper<roar_t>;
template<typename T>
void operator()(roar_t, T&, const std::vector<int>&) const { /* generic roar() goes here */ }
};
In the example I declare three helper types for the three methods I want to implement. The base_type introduces the purely virtual methods to VirtualBase and the derived_type<Actual> imports the implementations of these methods. To do so, I use virtual inheritance to resolve the occuring dreaded diamond ;)
One downside is that one has to declare virtual_crtp_helper types as friend in the derived classes. Maybe someone knows how to avoid that?
To sum up: To add a method to the class hierarchy, one has to
Declare a helper type for the method using virtual_crtp_helper<T> or const_virtual_crtp_helper<T>.
Have VirtualBase inherit from this type's base_type and define the method as generic template.
Have VirtualCRTP<Actual> inherit from the helper type's derived_type<Actual>.
For each derived class, implement the actual logic in templated and tagged operator().
I am happy to hear your thoughts and am looking forward to improvements.
Immanuel

C++ add virtual method in polymorphic subclass

I have cumbersome class and I want to refactor it to replace type code with subclasses. At some point during such process I have following hierarchy:
// interface
ISomeClass(){
public:
virtual foo() = 0;
virtual ~ISomeClass();
}
// this class is cumbersome one with huge amount of conditional logic based on type
BaseSomeClass : public ISomeClass(){
public:
virtual foo(){
if(TYPE_0 == getType()){ // finally I want to move such conditional logic in subclass
doSmth();
} else if (TYPE_1 == getType()){
doAnother();
}
}
protected:
virtual int getType(){ // I temporary need it for refactoring issue
return type_; // to replace type_ with subclasses
}
private:
int type_;
};
// this classes is almost empty now, but I want to move there all conditional logic in future
class Implementation1 : public BaseSomeClass {
virtual int getType(){ // I temporary need it for refactoring issue
return TYPE_0; // to replace type_ with subclasses
}
};
class Implementation2 : public BaseSomeClass {
virtual int getType(){ // I temporary need it for refactoring issue
return TYPE_1; // to replace type_ with subclasses
}
};
In BaseSomeClassdefined additional virtual method getType(). Would this method behavior be polymorphic if I handle all the instances using some kind of interface ISomeClass pointer? Assuming the interface itself doesn't provide such virtual method. Please notice this code is a first step in refactoring, not final one. Also this is a simplified example and real code has tens of such methods, I need to do refactoring step by step. And the question is about C++ dynamic polymorphism.
You asked:
Would this method behavior be polymorphic if I handle all the instances using some kind of interface ISomeClass pointer? Assuming the interface itself doesn't provide such virtual method.
If the interface does not provide such a virtual method, you can't expect polymorphic behavior.
It'll be better to implement foo in Implementation1 and Implementation2.
class BaseSomeClass : public ISomeClass()
{
};
class Implementation1 : public BaseSomeClass
{
virtual void foo()
{
doSmth();
}
};
class Implementation2 : public BaseSomeClass
{
virtual void foo()
{
doAnother();
}
};
If you must use getType(), you can resort to template based polymorphic behavior.
template <typename D>
class BaseSomeClass : public ISomeClass()
{
public:
virtual foo()
{
int type = D::getType();
if(TYPE_0 == type)
{
doSmth();
}
else if (TYPE_1 == type)
{
doAnother();
}
}
};
Here, you are expecting D to provide the interface getType(). You might as well expect D to provide the interface foo.
template <typename D>
class BaseSomeClass : public ISomeClass()
{
public:
virtual void foo()
{
D::foo():
}
};

wrapper to template class inherited by another class

template <class CollectionItem>
class Collection
{
void A();
// Many other utility functions
}
class ICollection
{
virtual void B() = 0;
}
class Base : public Collection<BaseItem>, public IBase
{
virtual void B();
}
Is there any way of offering Collection functions via ICollection interface without wrapping all the functions in Base class? ICollection : public Collection<CollectionItem> is not an option.
Bounty Update:
OK, so the original idea was to have Interface to all Collection classes. Before we continue, every CollectionItem also has Interface, let's call it ICollectionItem and ICollection only knows about ICollectionItem.
So what I did was create another template class as Interface to Collection template class - ICollection (pure virtual) accepting ICollectionItem(s). Collection class inherits this interface.
Every Collection class (inheriting Collection<CollectionItem> class) would also inherit it's Interface Collection class. That Interface then virtual inherits ICollection<ICollectionItem>. I'll just post the code :)
Here is the code:
template <class ICollectionItem>
class ICollection
{
public:
virtual const ICollectionItem* At(const int idx) = 0;
};
template <class CollectionItem, class ICollectionItem>
class Collection
: public ICollection,
public virtual ICollection<ICollectionItem> // Weak point
{
private:
List<CollectionItem*> fContainer;
public:
Collection(void) {}
virtual ~Collection() {}
virtual const ICollectionItem* At(const int idx); // Casting GetAt result
virtual const TCollectionItem& GetAt(const int idx) const
virtual ListIterator<TCollectionItem> >* GetIterator(void) const;
virtual ListIterator<ICollectionItem> >* Iterator(void) const; // Weak point
}
Example usage:
class IBaseItem
{
public:
virtual int Number() = 0;
{
class BaseItem
: public IBaseItem
{
public:
virtual int Number();
void SetNumber(int value);
}
class IBase
: public virtual ICollection<IBaseItem>
{
public:
virtual IBaseItem* ItemByName(String name) = 0;
virtual ~IBase() {}
}
class Base
: public Collection<BaseItem, IBaseItem>,
public IBase
{
public:
BaseItem* GetItemByName(String name);
virtual IBaseItem* ItemByName(String name);
}
Weak points:
First is at using virtual inheritance ... lots written about it, not much to talk about, or is it?
Unable to access Iterator using ICollection interface. See ListIterator function, only first one can be implemented, the second one would require some kind of new List of IBaseItem. I decided to live with that and just use for loop.
Even tho I somehow managed to get what I wanted (With wrapping and casting), I would still like to hear an second opinion. I don't like using virtual inheritance, specially in such delicate situations - using Collections for application Base creation.
I can not see any other solution than calling some Collection method in Base implementation of IBase virtual methods.
class Base : public Collection<BaseItem>, public IBase
{
virtual void B()
{
A();
}
}
You say, and I quote:
I want to call Collection functions using IBase pointer
I really don't see what is to be done here besides dynamic_cast. It does exactly what you want it to do.
void fun(IBase * base) {
auto * coll = dynamic_cast<Collection<BaseItem>*>(base);
if (coll) {
coll->A();
}
}
Your Collection class must have a virtual destructor.
You can, of course, offer a templated version, if you'd need different baseitems in different, scenarios for some reasons. This has bad code smell and I think your architecture is bad at this point, but oh well.
template <typename T> void fun(IBase * base) {
auto * coll = dynamic_cast<Collection<T>*>(base);
if (coll) {
coll->A();
}
}
void test(IBase * p) {
fun<BaseItem5>(p);
}
If you have some other specific scenario in mind, please edit your question to say what you mean.
Hmm...So you wanna to reuse the Collection class's utility functions, and you want to design a class which will implement an interface defined by IBase. As you mentioned above,"wrapping all the functions in Base class" is a way to offer Collection functions.
(1) Via inheritance,derived class has a good knowledge of Collection
class Derived:public Collection<DerivedType>,public IBase{};
or
template <typename T>
class Derived:public Collection<T>,public IBase{};
(2) Via inheritance,derived class knows little about Collection,but through IBase
class IBase : public Collection<BaseItem>{};
class Derived:public IBase{};
By (1),If you want to call Collection functions using IBase pointer,you have to wrap the functions.
By (2), any Derived instance is " a kind of " IBase which is "a kind of " Collection. So you can use IBase pointer to call Collection functions.
So,the key point is that the objects pointed by the IBase pointer should have the method you want to call.Wrap it or inherit it. I can not see any other solution than these two ways.
Edit: the idea is refined based on your example:
Here is an idea:
//generic interface can be kept as it is
template <class ICollectionItem>
class ICollection
{
public:
virtual const ICollectionItem* At(const int idx) = 0;
};
class Empty
{
};
template <class CollectionItem , class BaseClass = Empty>
class GenericCollection
: public BaseClass
{
public:
const CollectionItem* At(const int idx);
// At and ItemByName are standard functions for a collection
CollectionItem* ItemByName(String name);
//note that here nothing has to be declared as virtual
};
//example usage:
class IBase
: public virtual ICollection<IBaseItem>
{
public:
virtual IBaseItem* ItemByName(String name) = 0;
virtual ~IBase() {}
};
class Base
: public GenericCollection<BaseItem, IBase >
{
public:
//nothing to be implemented here, all functions are implemented in GenericCollection and defined as virtual in IBase
//The definition of the functions has to be the same:
};
In collection you can implement whatever and in the interface you can define what ever you want to be virtual from your collection. The only thing is that you need to have some standard in naming convention for functions.
Hope this helps,
Raxvan.
From your comments in another answer, it seems you want a collection of interfaces, and an implementation of this interface. The simplest I can advise you is the following:
template<typename T>
class ICollection
{
public:
virtual iterator<T>* begin() const = 0;
};
template<typename T, typename TBase>
class Collection : public ICollection<TBase>
{
public:
iterator_impl<T>* begin() const { return whatever; }
};
Example:
class IItem {};
class Item : public IItem {};
class Base : public Collection<Item, IItem> {};
old answer:
Is there any way of offering Collection functions via IBase interface without wrapping all the functions in Base class ?
If I understood your problem, you want to use it like this:
void myfunc()
{
// ...
IBase* obj = ...;
obj->A();
obj->B();
}
I think here is a misunderstanding here: if you want A() to be callable from an IBase, then you have to add it to Ibase declaration.
If you want to use the Collection functions on an object, then you should cast this object to a Collection, via dynamic_cast for example.
Furthermore, if you have such a funcion:
void fun(IBase* base) { /* ... */ }
you cannot cast to a Collection*, since there are no relationship between these two classes, unless you have another way to be sure base is a Collection:
void fun(IBase* base)
{
if(base && base->isABaseItemCollection())
{
// Valid, since the real type was checked before
Collection* collection = (Collection*)base;
// ...
}
}
On a side note: you can generate bases almost automatically:
template
class Base : public Collection, public U {};
typedef Base BaseCollection;
According to comment/chat:
You have something like:
class IAnimal { /*...*/ };
class Cat : public IAnimal { /*...*/ };
class Dog : public IAnimal { /*...*/ };
class Cats
{
std::vector<Cat*> cats;
public:
Cat* at(size_t index) { return cats[index]; }
/*...*/
};
class Dogs
{
std::vector<Dog*> dogs;
public:
Dog* at(size_t index) { return dogs[index]; }
/*...*/
};
And you want to factorize some code using something like
class IAnimals
{
public:
std::vector<IAnimals*> animals; // or getter/setter which works with IAnimals.
/* some common factorized code */
};
// And so
class Cats : public IAnimals { /**/ };
class Dogs : public IAnimals { /**/ };
I propose, instead of creating class IAnimals, to use template functions as:
template <typename TAnimals>
void foo(TAnimals& animals)
{
Ianimals* animal = animals.at(42);
// ...
animal->eat(food);
// ...
}
You have to give compatible "interface" (names) to the type used in template.
Maybe you could have an operator() in IBase that would be delegated to Base?
class CollectionBase {};
template <class Item> class Collection: public CollectionBase {};
class IBase
{
public:
virtual CollectionBase* operator()() = 0;
};
class Base : public Collection<BaseItem>, public IBase
{
public:
virtual Collection<BaseItem>* operator()() { return this; }
};

Use non-virtual dispatch in a template

I want to call a member function which is virtual (inheritance is used in most places to keep things simple), but I want to force calling it using non-virtual dispatch sometimes, in performance critical places, and in such places the exact type is known compile time. I do this for performance reasons, on a platform where virtual call performance is bad. For most functionality the overhead of virtual functions is fine, but for a few it is not. I would like to avoid duplicating all functions as both virtual and non-virtual.
Example:
class Interface
{
public:
virtual void Do(){}
};
class Implementation: public Interface
{
public:
virtual void Do(){}
};
void DoIt(Interface &func)
{
func.Do();
};
int main()
{
Implementation a;
DoIt(a);
// can DoIt be constructed as a template to avoid virtual dispatch?
return 0;
}
If you know the exact type you can do it as:
template <typename StaticType>
void DoIt(Interface &func)
{
static_cast<StaticType&>(func).StaticType::Do();
};
Where you need to manually downcast to the type you need (static_cast is fine if you do know the type). Then you need to qualify the method call, do disable dynamic dispatch.
struct DerivedType : Interface {
virtual void Do() { std::cout << "Derived::Do" << std::endl; }
};
struct MostDerived : DerivedType {
virtual void Do() { std::cout << "MostDerived::Do" << std::endl; }
};
void processDerived( Interface & iface ) {
DoIt<DerivedType>( iface );
}
int main() {
MostDerived obj;
DoIt<Derived>( obj ); // Will call Derived::Do
}
Note that using the qualified name will disable dynamic dispatch, and that means that it will not be dispatched to the runtime type of the object, but to the type that you tell it to call.
I think you are looking for Curiously Recurring Template Pattern (CRTP) which enables you static polymorphism :
template <typename Derived>
class Base {
public:
virtual ~Base() {}
void foo() { Derived::func_in_derived(); }
};
class Derived : public Base<Derived> {
public:
void func_in_derived() {}
};

C++ mixins via templates: why doesn't this work?

I've got a interface that's implemented as an abstract base class with a number of pure virtual public methods. These pure virtual functions can be implemented using a template since the differences between subclasses aren't large - so my idea was to use multiple inheritance to mix-in the appropriately templated helper-class that provides the implementation. However, the compiler complains that the base class is abstract; it isn't considering the helper mix-in's implementation so thinks there's no implementation of a required method.
For example:
class TrivialList {
int count;
public:
TrivialList(int count) : count(count){}
virtual double Average() const=0;
int Count() const {return count;}
virtual ~TrivialList(){}
};
template<typename TIndexable> class AverageHelper {
public:
double Average() const {
TIndexable const & self = static_cast<TIndexable const &>(*this);
double sum=0.0;
for(int i=0;i<self.Count();++) sum += self.Get(i);
return sum / self.Count();
}
};
class IndexableList : public TrivialList, public AverageHelper<IndexableList> {
std::vector<double> backend;
public:
IndexableList(int count) : TrivialList(count), backend(count) { }
double & Get(int i) { return backend[i];}
double const & Get(int i) const { return backend[i];}
};
IndexableList * MakeList() {return new IndexableList(5);} //error!
// cannot instantiate abstract class
I'm using MSC 10.0 (Visual Studio 2010); the code fails with a similar error using g++ 4.5.
Get or the real-world equivalents in my project cannot be virtual because they're extremely minor operations that need to be inlined for adequate performance (think put-pixel/get-pixel) - so I need the generic algorithms to be templated rather than generic via virtual function calls.
For implementing mix-ins via templates, you need the template implementing the abstract function to derive from the abstract base class.
So you may fix your code by changing it the following way:
// ...
template<typename TIndexable> class AverageHelper : public TriviaList{
// ...
class IndexableList : public AverageHelper<IndexableList> {
In general, if you want to provide more than one mix-in, you may either use a virtual inheritance in order not multiplying the instances of the base classes, or to use chain inheritance as in the following sample:
class Abstract {
public:
virtual void foo() = 0;
virtual void bar() = 0;
};
template<class Base>
class FooImpl : Base {
public:
void foo() { /* default foo implementation */ }
};
template<class Base>
class BarImpl : Base {
public:
void bar() { /* default bar implementation */ }
};
class Derived : public BarImpl<FooImpl<Abstract> > {
// You have both foo() and bar() implementations available
};
It doesn't work because AverageHelper<>::Average() doesn't override TrivialList::Average(). In order to override a virtual function, the overriding class must inherit from the class containing the function to be overridden.
You could change your template thus:
template<typename TIndexable, typename Base >
class AverageHelper : public Base {
public:
template< typename T >
AverageHelper(T arg) : Base(arg) {}
// ...
};
class IndexableList : public AverageHelper<IndexableList,TrivialList> {
public:
IndexableList(int count) : AverageHelper<IndexableList,TrivialList>(count) {}
// ...
};
You might want to virtually derive from TrivialList:
template<typename TIndexable, typename Base >
class AverageHelper : virtual public Base {
// ...
};