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() {}
};
Related
Suppose that I have a heirarchy of several classes:
class A {
public:
virtual void DoStuff() = 0;
};
class B : public A {
public:
// Does some work
void DoStuff() override;
};
class C : public B {
public:
// Calls B::DoStuff and does other work
void DoStuff() override;
};
It can naively be implemented:
void Derived::DoStuff() {
Base::DoStuff();
...
}
This implementation has a serious problem, I believe: one always has to remember to call base implementation when overrides.
Alternative:
class A {
public:
void DoStuff() {
for (auto& func: callbacks_) {
func(this);
}
}
virtual ~A() = default;
protected:
template <class T>
void AddDoStuff(T&& func) {
callbacks_.emplace_back(std::forward<T>(func));
}
private:
template <class... Args>
using CallbackHolder = std::vector<std::function<void(Args...)>>;
CallbackHolder<A*> callbacks_;
};
Usage:
class Derived : public Base {
public:
Derived() {
AddDoStuff([](A* this_ptr){
static_cast<Derived*>(this_ptr)->DoStuffImpl();
});
}
private:
void DoStuffImpl();
};
However, I believe that it has a good amount of overhead when actually calling DoStuff(), as compared to the first implementation. In the use cases which I saw, possibly long costruction of objects is not a problem (one might also try to implement something like "short vector optimization" if he wants).
Also, I believe that 3 definitions for each DoStuff method is a little too much boilerplate.
I know that it can be very effectively solved by using inheritance pattern simular to CRTP, and one can hide the template-based solution behind interface class (A in the example), but I keep wondering -- shouldn't there be an easier solution?
I'm interested in a good implementation of call DERIVED implementation FROM BASE, if and only if derived class exists and it has an overriding method for long inheritance chains (or something equivalent).
Thanks!
Edit:
I am aware of an idea described in #Jarod42's answer, and I don't find it appropriate because I believe that it is ugly for long inheritance chains -- one has to use a different method name for each level of hierarchy.
You might change your class B to something like:
class A {
public:
virtual ~A() = default;
virtual void DoStuff() = 0;
};
class B : public A {
public:
void DoStuff() final { /*..*/ DoExtraStuff(); }
virtual void DoExtraStuff() {}
};
class C : public B {
public:
void DoExtraStuff() override;
};
I am not sure if I understood correctly but this seems to be addressed pretty good by the "Make public interface non-virtual, virtualize private functions instead" advice.
I think it's orignated in the Open-Closed principle. The technique is as-follows:
#include <iostream>
class B {
public:
void f() {
before_f();
f_();
};
private:
void before_f() {
std::cout << "will always be before f";
}
virtual void f_() = 0;
};
class D : public B{
private:
void f_() override {
std::cout << "derived stuff\n";
}
};
int main() {
D d;
d.f();
return 0;
}
You essentially deprive descendant class of overriding public interface, only customize exposed parts. The base class B strictly enforces that required method is called before actual implementation in derived might want to do. As a bonus you don't have to remember to call base class.
Of course you could make f virtual as well and let D decide.
I have a method in a baseclass that needs the type passed to it for some type-related operations (lookup, size, and some method invocation). Currently it looks like this:
class base
{
template<typename T>
void BindType( T * t ); // do something with the type
};
class derived : public base
{
void foo() { do_some_work BindType( this ); }
};
class derivedOther : public base
{
void bar() { do_different_work... BindType( this ); }
};
However, I wonder if there's a way to get the caller's type without having to pass this so that my callpoint code becomes:
class derived : public base
{
void foo() { BindType(); }
};
Without the explicit this pointer. I know that I could supply the template parameters explicitly as BindType<derived>(), but is there a way to somehow extract the type of the caller in some other way?
There's no magical way to get the caller's type, but you can use CRTP (as a comment mentions) in order to automate this behavior, at the cost of a bit of code complexity:
class base
{
template<typename T>
void BindType(); // do something with the type
};
template <class T>
class crtper : base
{
void BindDerived { BindType<T>(); }
}
class derived : public crtper<derived>
{
void foo() { do_some_work BindDerived(); }
};
class derivedOther : public crtper<derivedOther>
{
void bar() { do_different_work... BindDerived(); }
};
Edit: I should mention, I would kind have expected that foo would be a virtual function, defined without implementation in base. That way you would be able to trigger the action directly from the interface. Although maybe you have that in your real code, but not in your example. In any case, this solution is perfectly compatible with this.
Edit2: After question edit, edited to clarify that solution still applies.
If you want to avoid BindType<derived>(), consider (a bit verbose, I agree) BindType<std::remove_reference<decltype(*this)>::type>(); to avoid passing a parameter. It gets resolved at compile-time and avoids run-time penalties.
class base
{
protected:
template<typename T>
void BindType() { cout << typeid(T).name() << endl; } // do something with the type
};
class derived : public base
{
public:
void foo()
{
BindType<std::remove_reference<decltype(*this)>::type>();
}
};
It will not work as you expect
The result of foo() might be different of what you expect:
class derived : public base // <= YOU ARE IN CLASS DERIVED
{
public:
void foo() { BindType( this ); } // <= SO this IS OF TYPE POINTER TO DERIVED
};
The template paramter is deducted at compile time, so that it will be derived*. If you would call foo() from a class derived_once_more derived from derived, it would still use the type derived*.
Online demo
But you can get rid of the dummy parameter*
You may use decltype(this) to represent the typename of a variable. It's still defined at compile time:
class base
{
public:
template<typename T>
void BindType( )
{
cout << typeid(T*).name()<<endl; // just to show the type
}
virtual ~base() {}; // for typeid() to work
};
class derived : public base
{
public:
void foo() { BindType<decltype(this)>( ); }
};
Online demo
Edit: other alternatives
As template parameters need to be provided at compile-time and not a run time, you can use:
template parameter deduction (your first code snippet)
decltype (see above)
if you intend to add this in all the derived classes you could use a macro to get it done, using one of the above mentionned solution
you could use the CRTP pattern (already explained in another answer).
A possible solution that avoids the intermediate class of the CRTP follows:
class base {
using func_t = void(*)(void *);
template<typename T>
static void proto(void *ptr) {
T *t = static_cast<T*>(ptr);
(void)t;
// do whatever you want...
}
protected:
inline void bindType() {
func(this);
}
public:
template<typename T>
base(T *): func{&proto<T>} {}
private:
func_t func;
};
struct derived1: base {
derived1(): base{this} {}
void foo() {
// ...
bindType();
}
};
struct derived2: base {
derived2(): base{this} {}
void bar() {
// ...
bindType();
}
};
int main() {
derived1 d1;
d1.foo();
derived2 d2;
d2.bar();
}
The basic idea is to exploit the fact that the this pointers in the constructor of the derived classes are of the desired types.
They can be passed as a parameter of the constructor of the base class and used to specialize a function template that do the dirty job behind the hood.
The type of the derived class is actually erased in the base class once the constructor returns. Anyway, the specialization of proto contains that information and it can cast the this pointer of the base class to the right type.
This works fine as long as there are few functions to be specialized.
In this case there is only one function, so it applies to the problem pretty well.
You can add a static_assert to add a constraint on T, as an example:
template<typename T>
base(T *t): func{&proto<T>} {
static_assert(std::is_base_of<base, T>::value, "!");
}
It requires to include the <type_traits> header.
I'm having a little issue with overriding static methods of base clases, but the whole question is very complicated and too long (generalization of resource management in game engine), so here's a simplified version:
template<class T>
class base
{
static void bar()
{ printf("bar"); }
public:
static void foo()
{ bar(); }
};
class derived : public base<int>
{
static void bar()
{ printf("baz"); }
};
int main() { derived::foo(); }
The code above outputs "bar" in my case, insted I want it to output "baz". How can I go about that? It seems that no matter what I attempt, base::foo() always calls base::bar(). I might have an issue with the design. I've never came across this problem - how can I resolve it?
What you're trying to do is not achievable with simple class inheritance; a method cannot be both static and virtual.
You need a static method to be able to call a function without an object (an instance); and you need bar to be virtual so that bar<int>::foo() calls derived::bar() when called from a derived instance.
Those two traits are mutually exclusive. But the Curiously Recursive Template Pattern (CRTP) may be a solution here:
#include <iostream>
template<class T>
struct base
{
static void foo()
{
T::bar();
}
};
struct derived : public base<derived>
{
static void bar()
{
std::cout << "derived" << std::endl;
}
};
int main()
{
derived::foo();
}
Live example
My code structure is like below where multiple classes implement Interface. In Example class I store a pointer to the Interface and new() it in the constructor appropriately (depending on constructor parameters not shown here). I'm looking for ways to avoid using new() in this scenario but haven't got a solution yet. What's the best practice for something like this?
class Interface
{
virtual void Foo() = 0;
};
class A : public Interface
{
void Foo() { ... }
};
class B : public Interface
{
void Foo() { ... }
};
class Example
{
private:
Interface* m_bar;
public:
Example()
{
m_bar = new A(); // deleted in destructor
}
};
There are two ways this is typically done, each with their own merits.
If A is truely defined at compile time, than a typical way to handle this is to simply use a template type:
template <typename T>
class TemplateExample
{
T m_bar;
public:
TemplateExample() : m_bar() {};
}
This has some downsides. TemplateExample<A> becomes unrelated to TemplateExample<B>, the error messages when T doesn't follow the correct interface are pretty obtuse, ect. The upside is this may use duck typing rather than interface typing, and m_bar is a concrete instance.
The other (arguable more common) way is to do the following
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
};
This has the benefit of being able to be run time configuratble if you follow a cloable pattern:
class Interface
{
public:
virtual void Foo() = 0;
virtual Interface* clone() const = 0;
};
template <typename T>
class CloneHelper : public Interface
{
public:
virtual Interface* clone() const { return new T(static_cast<const T&>(*this));}
};
class A : public CloneHelper<A>
{
virtual void Foo() { std::cout << 'A' << std::endl; }
};
class B : public CloneHelper<B>
{
virtual void Foo() { std::cout << 'B' << std::endl; }
};
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
UniquePtrExample(const Interface& i) : m_bar(i.clone());
};
Note you can further extend the above to have a move variant of the clone function.
Please help me solve this problem. WhiteDragon is to call Dragon::attacks() instead of
MonsterImplement::attacks(), and there is ambiguity error here. If I change Dragon to
be derived from MonsterImplement, then the line
std::cout << monster->numAttacks << std::endl; won't compile because Dragon has no numAttacks data member (nor should it, because different types of Dragons are to have different values). So I need WhiteDragon to call Dragon::attacks() and to call finalizeMonster() during its instantiation. If I make Dragon virtual derived class of Monster, WhiteDragon calls up MonsterImplement::attacks() instead.
#include <iostream>
struct Monster {
virtual void finalizeMonster() {}
virtual void attack() {}
};
template <class MONSTER, int NUM>
struct MonsterInt: virtual public Monster {
static int numAttacks;
};
template <class MONSTER, int NUM>
int MonsterInt<MONSTER, NUM>::numAttacks = NUM;
template <class BASE, class MONSTER>
struct MonsterImplement: virtual public BASE {
MonsterImplement() {finalizeMonster();}
virtual void finalizeMonster() override;
virtual void attack() override {std::cout << "MonsterImplement::attack()" << std::endl;}
};
struct Dragon: public Monster { // or Dragon: public MonsterImplement<Monster, Dragon> ?
// but then Dragon will also call the MonsterImplement constructor (when it has no numAttacks member)
virtual void attack() override {std::cout << "Dragon::attack()" << std::endl;}
};
struct WhiteDragon: public MonsterInt<WhiteDragon, 3>,
public MonsterImplement<Dragon, WhiteDragon> {
WhiteDragon(): MonsterImplement<Dragon, WhiteDragon>() {}
};
template <class BASE, class MONSTER>
inline void MonsterImplement<BASE, MONSTER>::finalizeMonster() {
MONSTER* monster = static_cast<MONSTER*> (this);
std::cout << monster->numAttacks << std::endl;
}
int main() {
WhiteDragon wd;
wd.attack();
}
(Copied from an earlier comment.)
Perspective #1
CRTP is meant to provide non-dynamic behavior. If the value of "numAttacks" vary with each derived class, this is not a "non-dynamic" situation. A counter-example would be to put a non-static non-virtual method int numAttacks() { return 3; } in a derived class, and then in the CRTP base class add some methods (the attack logic that is shared across all derived classes), which can then call the numAttacks() method on its derived class, without incurring a virtual function call.
Example:
struct Monster
{
virtual void attack() = 0;
virtual int getNumAttacks() const = 0;
};
template <struct MONSTER>
struct AttackLogic : virtual public Monster
{
virtual void attack() override
{
/* allowed to call MONSTER::getNumAttacks(), renamed to avoid confusion. */
int numAttacks = static_cast<MONSTER*>(this).getNumAttacks();
/* Use the value in attack calculations. */
}
};
struct Unicorn
: virtual public Monster
, virtual public AttackLogic<Unicorn>
{
virtual int getNumAttacks() const override
{
return 42; // Unicorn is awesome
}
};
Disclaimer: Code only meant to explain my suggestion. Not intended for practical use. Not tested with compiler. My knowledge of virutal inheritance is weak, so there may be mistakes or broken guidelines in the sample code above.
Your current inheritance chain is: (base at top)
Monster
Dragon
MonsterImplement<Dragon, WhiteDragon>
WhiteDragon
Monster defines:
virtual finalizeMonster() // abstract
virtual attack() // abstract
Dragon defines:
virtual attack() // concrete, overrides Monster.attack()
MonsterImplement<...> defines:
virtual attack() // concrete, overrides Dragon.attack() and Monster.attack()
WhiteDragon defines:
(no new virtual methods defined)
It is very clear that "after fixing the bug", that MonsterImplement.attack() will be called, because it is a subclass of Dragon and therefore overrides it.
In general it only says that the current inheritance hierarchy is badly designed, and that nobody would be able to fix it.
Perspective #2
Injecting a static int through CRTP pattern is rarely worth the effort. CRTP is more suitable for injecting a set of non-static, non-virtual methods ("boilerplate") in a way that will not be overridden, that saves every derived class from re-implementing the same "boilerplate".
At the minimum, convert the static int numAttacks into a virtual function
virtual int numAttacks() const { throw std::exception(); }
or
virtual int numAttacks() const = 0; // abstract
and then provide a concrete implementation in WhiteDragon to return 3.
struct WhiteDragon : ...
{ ...
virtual int numAttacks() const override { return 3; }
...
};
template <class MONSTER, int NUM>
struct MonsterInt: virtual public Monster {
static int numAttacks;
};
What's the purpose of this class? It seems like all it does is give a class a number of attacks, in which case it doesn't really make sense to derive from monster.
template <int NUM>
struct MonsterInt {
static int numAttacks;
};
That 'fixes' the program I think, but it's hard to really say because intention is hard to derive from your code.