I am using CRTP for some classes. However, I need to homogeneously store these classes for example in an std::vector.
A solution would be to have a common abstract base class. For example, as explained in the wikipedia page on CRTP :
// Base class has a pure virtual function for cloning
class Shape {
public:
virtual ~Shape() {};
virtual void draw() = 0;
};
// This CRTP class implements clone() for Derived
template <typename Derived>
class Shape_CRTP : public Shape {
public:
void draw() {
static_cast<Derived const&>(*this)->draw();
}
};
class Square: public Shape_CRTP<Square> {
void draw() {/// implement draw}
};
class Circle: public Shape_CRTP<Circle> {
void draw() {/// implement draw}
};
and in the main :
std::vector<Shape*> shapes;
for (auto s : shapes) {
s->draw();
}
But in this case, don't I lose the benefits of static polymorphism as I will have the virtual call overhead (draw is virtual in the common base class), and as my draw implementations will not be inlined?
Please explain and point me to references if you have some
First and most important, let's state the reason for CRTP: it is a tool for code reduction. The corresponding base class is hardly ever used by itself, but rather to implement functions which are shared by several derived classes (and which you'd otherwise would have to retype in any derived class anew).
In CRTP, it is good style to separate the "pure virtual functions", which are to be implemented in the derived class, via their name. I usually use the suffix _impl for that and put the functions in protected scope. This directly tells you which of the functions in the CRTP base class one should implement in derived classes (whereas the others would work out of the box).
Applied to your example this would look like the following:
struct Shape {
virtual ~Shape() {};
virtual void draw() const = 0;
};
template <typename Derived>
struct Shape_CRTP : public Shape {
protected:
void draw_impl() const = delete;
public:
virtual void draw() const override final {
static_cast<Derived const&>(*this).draw_impl();
}
};
struct Square: public Shape_CRTP<Square> {
friend Shape_CRTP<Square>;
protected:
void draw_impl() const {/* implement draw */}
};
struct Circle: public Shape_CRTP<Circle> {
friend Shape_CRTP<Circle>;
protected:
void draw_impl() const {/* implement draw */}
};
Let's look at this from the perspective of performance:
When you work with a pointer to the virtual base class Shape, the previous solution is equivalent to yours. In both cases you have a dynamic access via a vtable, and this has the same overhead regardless of the dept of the inheritance hierarchy (i.e. regardless whether you point to Square as in your solution or to Shape_CRTP<Square> as in mine).
When you work directly with the derived class Square, it's also equivalent, because then the compiler can call the draw() function directly (either via the derived class in your solution or via the CRTP base in mine).
And, as said, one hardly ever works with Shape_CRTP directly, so there is also no point in analysing its behavior.
Summarizing, CRTP has no effect on the runtime performance here. So, why you should need CRTP at all? Again, for code reduction! An this pays out the most, if you have
either only a few _impl() functions to derive from, and a whole lot of functions in the CRTP base class, or
a lot of different derived classes, where saving a few function implementations could be worth it.
Depending on the actual problem, CRTP can save thousands lines of code, and in general, it's a great tool exactly for that.
Related
I am working on a bounding box/collision detection system and I am using different types of bounding volumes, id like all the bounding volumes to derive the same base class and then using pure virtual functions forcing all derived classes to implement basic functions like
isCollidingWith(BoudingBox)
But here is what giving me trouble: I wan't them to implement a function for every BoudingVolume type. So if I have a bounding box and a bounding sphere, both the sphere class and the box class should implement
isCollidingWith(BoundingBox)
isCollidingWith(BoundingSphere)
If i then create a new BoundingVolume like BoundingCylinder (by deriving from the base class), i want the compiler to throw an error until BoundingBox and BoundingSphere has implemented the isCollidingWith function for the new Cylinder type (and ofc until the Cylinder has implemented the isCollidingWith for the Box, Sphere and the Cylinder.
Im not sure on how to go about implementing this, but I thought about using CRTPs.
Is this even possible?
When you make pure virtual function in base class, then it is compulsory for derived class for its implementation, if derived class doesn't implement it then compiler will give you an error. so you don't have to take care whether the pure virtual functions are implemented or not.
It is possible to concoct such a thing with CRTP
class BoundingBox;
class BoundingSphere;
class Shape
{
public:
virtual bool isIntersecting(const BoundingBox&) const = 0;
virtual bool isIntersecting(const BoundingSphere&) const = 0;
};
class BoundingVolumeBase
{
public:
virtual bool checkIntersection(const Shape&) const = 0;
virtual ~BoundingVolumeBase();
};
template<class Derived>
class BoundingVolume : public BoundingVolumeBase
{
bool checkIntersection(const Shape& shape) const override
{
return shape.isIntersecting (static_cast<const Derived&>(*this));
}
};
class BoundingBox : public BoundingVolume<BoundingBox> {
// ...
};
class BoundingSphere : public BoundingVolume<BoundingSphere> {
// ...
};
Now if we invent a new kind of BoundingVolume, it will not compile until a new function is added to Shape.
class BoundingCylinder : public BoundingVolume<BoundingCylinder> {
// ...
};
BoundingCylinder bc; // <-- this will not compile
It is not necessary to do it this way. Any method that uses virtual functions as the sole kind of type-based dispatch will work (you will likely end up with something roughly equivalent to the above anyway). If you depend on typeid or on a custom type identifier, you may encounter problems though.
The downside of this method is mutual dependence of class Shape and all concrete kinds of BoundingVolume.
I usually try to find answers here before I post anything, but I'm not even sure how to formulate my question.
So here's what I want to do... I want to define a Base Interface, and a Derived Interface. Then, I want to implement the Base Interface, with extra variables and methods. Finally, I want to implemented a Derived class, from the implemented Base Interface BUT ALSO from the Derived Interface. I don't know about you, but my head hurts.
If I do something like below, I get Ambiguous definitions under the DerivedFloat code since that code "sees" both the GetBaseValue method from the IBase, inherited through IDerivedFloat, as well as the GetBaseValue inherited from Base.
Surely, there must be a way to derive a class which uses the expanded features of the Base Implementation, as well as making sure it implements the required IDerivedFloat methods.
Now... This is a dummy example to show what I'm conceptually trying to achieve. It's not a real life example.
template <typename VALUE_TYPE>
class IBase
{
public:
virtual VALUE_TYPE GetBaseValue() const = 0;
};
class IDerivedFloat : public IBase<FLOAT>
{
public:
virtual void SetBaseValue(const FLOAT & value) = 0;
};
// Implementation of Base
template <typename VALUE_TYPE>
class Base : public IBase<VALUE_TYPE>
{
public:
VALUE_TYPE GetBaseValue() const { return m_BaseValue; }
protected:
VALUE_TYPE m_BaseValue;
}
// Uses expanded Base AND implements IDerivedFloat
class DerivedFloat : public Base<FLOAT>, public IDerivedFloat
{
public:
void SetBaseValue(const FLOAT & value) { m_BaseValue = value };
}
You can use virtual inheritance to work around this problem:
class IDerivedFloat : virtual IBase<FLOAT>
{
public:
virtual void SetBaseValue(const FLOAT & value) = 0;
};
template <typename VALUE_TYPE>
class Base : virtual IBase<VALUE_TYPE>
{
public:
VALUE_TYPE GetBaseValue() const { return m_BaseValue; }
protected:
VALUE_TYPE m_BaseValue;
}
Using virtual inheritance gives the derive class one instance of the base class members, instead of one from each time it exists in the class hierarchy.
Multiple inheritance is an issue precisely because of the ambiguity issue you ran into, but there are ways to get around it. You have to explicitly tell the compiler which super you are calling the ambiguous functions from, by leading the function call with the super's name and a double colon.
Example:
- C inherits from A and B.
- A and B both have add() function.
- In C, you have to say A::add() or B::add() to tell the compiler which one to use.
Link for details and more complete implementation: http://www.cprogramming.com/tutorial/multiple_inheritance.html
I have such hierarchy of classes:
template <class Type>
class CrtpBase
{
protected:
Type& real_this()
{
return static_cast<Type&>(*this);
}
};
template <class ChildType>
class Base : CrtpBase<ChildType>
{
public:
void foo()
{
this->real_this().boo();
}
};
class Derived1 : public Base<Derived1>
{
public:
void boo { ... }
};
class Derived2 : public Base<Derived2>
{
public:
void boo { ... }
};
The thing is, I want to use my classes in this way:
std::vector<Base*> base_vec;
base_vec.push_bach(new Derived1());
base_vec.push_bach(new Derived2());
.........
base_vec[0]->foo();
But this isn't possible, because base class for all derived classes is different (actually Base isn't a type at all, it's template). So, is there a way to use crtp with multiple derived classes, alongside with polymorphism?
Indeed there is, you need to add the appropriate non-template base class too:
class AbstractBase
{
public:
virtual ~AbstractBase() {}
virtual void foo() = 0;
};
template <class ChildType>
class Base : CrtpBase<ChildType>, public AbstactBase
{
void foo() override { this->real_this().boo(); }
};
Then, declare your vector as std::vector<AbstractBase*>.
This does indeed introduce the overhead of dynamic dispatch (which you were probably trying to avoid by using CRTP), but dynamic dispatch is the only way to get runtime polymorphism in C++.
It can still be beneficial, though. For example, if the implementation of foo is shared by all the derived classes, but calls into many different boo-style functions (with each derived class having a different implementation of those), you will only pay the dynamic dispatch cost once when invoking foo, and then all the calls made within foo are dispatched statically, CRTP-style.
On the other hand, if it's just one call to a boo-like function within foo, you may as well make boo virtual, put non-virtual foo into the base, thus getting rid of CRTP. The cost will be the same then: a non-virtual dispatch (foo) and a virtual one (boo).
Side note, you should strongly consider storing smart pointers in the std::vector; owning raw pointers are bad practice.
I thought of using protected constructor, but it couldn't completely solve the purpose since the class inheriting from it would be able to instantiate the base class.
As for private constructor, the derived classes too would not be instantiated.
So, any suitable technique would be appreciated.
It is unclear what you are really asking for. So let me try to clear some points:
Pure virtual functions can have definitions
If your concern is that you want to provide definitions for all of the virtual functions in your base you can provide the definitions for the pure virtual functions, and they will be available for static dispatch.
Protected grants access to your base subobject, not to every instance of base
There is a common misconception that protected allows a particular derived type accessing any instance of base. That is not true. The keyword protected grants access to the base subobject within the derived type.
class base {
protected: base() {}
};
class derived : public base {
derived() : base() { // fine our subobject
base b; // error, `b` is not your subobject
}
};
The definition of an abstract class is one that has at least one pure virtual function (virtual function-signature = 0; You can't create an abstract class without them.
Can an abstract class be implemented without pure virtual functions in C++?
If you choose the point of view from Static Polymorphism, you can do that!
An abstract base class would be simply missing a default method implementation for an interface method from the deriving class.
Additionally you can use protected constructors for those CRTP base class templates, to require inheritance for instantiation.
UPDATE:
I found a nice slide show, that explains static vs dynamic polymorphism comprehensively. Each technique has it's pros and cons and certain fields of usage, additionally you can mix both techniques (wisely of course).
To elaborate a bit, I'll give a sample:
template<class Derived>
class AbstractBase
{
public:
// Equivalent for a pure virtual function
void foo()
{
// static_cast<> enforces an 'Is a' relation from Derived to AbstractBase
static_cast<Derived*>(this)->fooImpl();
}
// Equivalent for simple virtual function (overidable from Derived)
void bar()
{
static_cast<Derived*>(this)->barImpl();
}
// Default implementation for any call to bar()
void barImpl()
{
}
protected:
AbstractBase() {}
};
// Compilation will fail, since ConcreteClass1 doesn't provide
// a declaration for fooImpl()
class ConcreteClass1
: public AbstractBase<ConcreteClass1>
{
}
// Compiles fine
class ConcreteClass2
: public AbstractBase<ConcreteClass2>
{
public:
void fooImpl()
{
// Concrete implementation ...
}
}
The following sample shows that the pattern introduced above enforces an 'Is a' relationship between abstract class and inheriting class (the template parameter)
class ConcreteClass3
{
public:
void fooImpl()
{
// Concrete implementation ...
}
}
// Instantiation will fail, because
// * the constructor is protected
// * at least the static cast will fail
AbstractBase<ConcreteClass3> instance;
I read it in my book
An abstract class is a class that is designed to be specifically used as a base class. An abstract class contains at least one pure virtual function. You declare a pure virtual function by using a pure specifier (= 0) in the declaration of a virtual member function in the class declaration.
In C++ an interface can be implemented by a class whose methods are pure virtual.
Such a class could be part of a library to describe what methods an object should implement to be able to work with other classes in the library:
class Lib::IFoo
{
public:
virtual void method() = 0;
};
:
class Lib::Bar
{
public:
void stuff( Lib::IFoo & );
};
Now I want to to use class Lib::Bar, so I have to implement the IFoo interface.
For my purposes I need a whole of related classes so I would like to work with a base class that guarantees common behavior using the NVI idiom:
class FooBase : public IFoo // implement interface IFoo
{
public:
void method(); // calls methodImpl;
private:
virtual void methodImpl();
};
The non-virtual interface (NVI) idiom ought to deny derived classes the possibility of overriding the common behavior implemented in FooBase::method(), but since IFoo made it virtual it seems that all derived classes have the opportunity to override the FooBase::method().
If I want to use the NVI idiom, what are my options other than the pImpl idiom already suggested (thanks space-c0wb0y).
I think you've got your NVI pattern around the wrong way:
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface
Not sure if that solves your issue though.
class IFoo
{
public:
void method() { methodImpl(); }
private:
virtual void methodImpl()=0;
};
class FooBase : public IFoo // implement interface IFoo
{
private:
virtual void methodImpl();
};
Here's an example of why you might do this using a reader that reads from XML and another from DB. Note that common structure is moved into the NVI readFromSource, while non-common behaviour is moved into the private virtual getRawDatum. This way logging and error checking is only needed in the one function.
class IReader
{
public:
// NVI
Datum readFromSource()
{
Datum datum = getRawDatum();
if( ! datum.isValid() ) throw ReaderError("Unable to get valid datum");
logger::log("Datum Read");
return datum;
}
private:
// Virtual Bits
Datum getRawDatum()=0;
};
class DBReader : public IReader
{
private:
Datum getRawDatum() { ... }
};
class XmlReader : public IReader
{
private:
Datum getRawDatum() { ... }
};
Commonly, the reason for using the NVI (sometimes also called "Template Method") is that derived classes should only change a part of the base class' behavior. So what you do is this:
class base {
public:
void f()
{
// do something derived classes shouldn't interfere with
vf();
// do something derived classes shouldn't interfere with
vg();
// do something derived classes shouldn't interfere with
vh();
// do something derived classes shouldn't interfere with
}
private:
virtual void vf(); // might be pure virtual, too
virtual void vg(); // might be pure virtual, too
virtual void vh(); // might be pure virtual, too
};
Derived classes can then plug into f() at the spots they are meant to and change aspects of f()'s behavior, without messing up its fundamental algorithm.
It may be confusing that once a method is declared as virtual in a base class, it automatically becomes virtual in all derived classes, even if the virtual keywords is not used there. So in your example, both methods of FooBase are virtual.
... to deny derived classes the
possibility of overriding the common
behavior implemented in
FooBase::method()...
If you can get rid of IFoo, and just start the hierarchy with FooBase with a non-virtual method, that would do it. But it looks like you want to allow direct children of IFoo to override method(), but to prevent children of FooBase to override it. I don't think that's possible.
You could use the pimpl-idiom to achieve this:
class IFoo
{
public:
IFoo( boost::shared_ptr< IFooImpl > pImpl )
: m_pImpl( pImpl )
{}
void method() { m_pImpl->method(); }
void otherMethod() { m_pImpl->otherMethod(); }
private:
boost::shared_ptr< IFooImpl > m_pImpl;
};
class IFooImpl
{
public:
void method();
virtual void otherMethod();
};
Now others can still subclass IFooImpl and pass it to IFoo, but they cannot override the behavior of method (they can override otherMethod). You can even make IFooImpl a direct subclass of IFoo and use enable_shared_from_this to initialize IFoo correctly. This is just the gist of the method. There are many ways to tweak this approach. For instance you can use the factory-pattern to make sure IFoos are created correctly.
Hope that helps.