avoid vtable mixup in c++ variadic template inheritance - c++

I have an idea to architecting classical entity-component in a better way with variadic template inheritance. This question stems from funky experiments in the context of 3d-graphics but i believe i have it broken down to a very abstract question about C++. I am able to use C++20 in the scope in which it is currently implemented in Microsoft cl aka. the MSVC++19-Toolchain.
So. A few Base classes:
class basic {
public:
std::wstring get_name() { return name; }
virtual void do_something_idk_virtual() = 0;
virtual ~basic() {}
private:
std::wstring name;
}
class has_legs {
public:
virtual void walk() = 0;
virtual ~has_legs() {}
}
class has_wings {
public:
virtual void fly() = 0;
virtual ~has_wings() {}
}
template<typename... Ts>
class entity : public basic, public Ts... {
public:
virtual ~entity() {}
}
So far, so good. Now i want to make a duck:
class duck : entity<has_wings, has_legs> {
public:
virtual ~duck() {}
virtual void walk() { cout << "walk" << endl; }
virtual void fly() { cout << "fly" << endl; }
virtual void do_something_idk_virtual() { } // nothing,
}
still, seems to work. The problem is: I know have data structure (say a linked_list, or some sort of graph) and I use the visitor-pattern to work with basic*-typed things. I now have a lot of Code that looks like this. This is, quite literally, the central and critical part of a my program:
void visit(basic* node) {
//here i find out, through magic or some other kind of out-of-scope-mechanism that node is at least a has_wings. Problem:
reinterpret_cast<has_wings*>(node)->fly(); //does not work, will call basic::do_something_idk_virtual(). As far as i understand, this is because the compiler-generated vtable does not change via the reinterpret_cast.
reinterpret_cast<entity<has_wings>*>(node)->fly(); //might, work, problems start to come in if node is of some type that has_wings and has_legs. It sometimes calls some other method, depending on the ordering in declaring the class.
}
Solution
Have every component (aka. the pure interfaces) and the entity-class virtually inherit from basic
in basic add the non-virtual method:
template<typename TComponent> TComponent* get_component() {
return dynamic_cast<TComponent*>(this);
}
This will then fix vtables. I am not sure why dynamic_cast does that.

First of all, your template gives you nothing. class duck : public basic, public has_wings, public has_legs is absolutely identical.
Second, you need to decide what your level of polymorphic access is. If your level is basic, than it has to have already defined all the virtuals you want to be accessing (i.e. has_wings, fly) An interface where you need dynamic_casts to arrive to correct dynamic type (your example with reinterpret_cast is just wrong, you can't use reinterpret_cast to move through class hierarchy) is a poorly written interface.
Sometimes visitor pattern can be employed, but in my mind, it tends to produce extremely hard to troubleshoot code.

You have to use static_cast or dynamic_cast to move within an inheritance hierarchy, and static_cast can’t descend virtual inheritance or cross-cast (in one step) because the layout of different classes that derive from the source and destination types may differ. As it is, you’d have to know the actual type (not just that it had a given aspect) to do the conversion. If you have your “aspect” classes inherit from basic—virtually, so that there is a unique basic* to be had—you can then use dynamic_cast not for its checking purpose but so as to find the appropriate vtable for the aspect in question.
If you can’t afford that, you may want to amalgamate the interfaces somehow. You then have to be careful to call the functions only when they’re meaningful; that’s already the case (“through magic”), but then the ordinary call syntax might be an attractive nuisance. You might also try some C-style polymorphism with a manually-created vtable with function pointers for each optional behavior.

Related

Is there a way to decrease the size of the object by removing "vptr"

I have a code like this using CRTP and C++20:
template<class Derived>
class Base {
public:
void m() {
static_cast<Derived*>(this)->feature();
}
virtual constexpr void feature() = 0;
}
class BaseImpl: public Base<BaseImpl> {
virtual constexpr void feature() final override { // ... };
}
Is there a way to remove vptr so the object won't take 8 bytes (for x64), and instead will take only 1 byte? (since it never uses runtime polymorphism)?
In real code, the hierarchy is much more complex and it has 2 vptr (so it takes 16 bytes). Are there any extensions like for GCC or MSVC?
Yeah, definitely, one of the solutions is just to remove the virtual method. But since it has a complex hierarchy, it brings extremely ugly errors and unmaintainable code, since programmers should guess what methods must be implemented via reading unreadable template instantiation errors.
The whole goal is to achieve a Java-like hierarchy (with interfaces, override checks, etc), but with zero-cost abstraction.
I did some experiments (exploring code disassembly) and the compiler completely optimized all the virtual calls, providing zero-cost abstraction. EXCEPT it extends the object to have a vptr which is never used in my code.
I found something like __declspec(novtable) but vptr still takes space.
And yes, the size of the objects is extremely important to be as small as possible.
You're using CRTP, which uses static dispatch. There's absolutely no reason to use virtual here. If you want to ensure that the method exists with the right signature, use a static_assert.
template<class Derived>
class Base {
public:
void m() {
static_cast<Derived*>(this)->feature();
}
~Base() {
static_assert(std::is_same_v<void,decltype(static_cast<Derived*>(this)->feature())>);
}
};
class BaseImpl: public Base<BaseImpl> {
public:
constexpr void feature() { };
};

dynamic_cast vs virtual AsDerived method in base

When trying to access derived class behaviour, the most common approach I read about is using dynamic_casts, i.e. dynamic_cast<DerivedA*>(BasePtr)->DerivedAOnlyMethod(). This isn't really pretty, but everybody understands what's going on.
Now I'm working on a code where this conversion is handled by virtual functions exported to the base class, for each derived class, i.e.:
class Base
{
public:
virtual DerivedA* AsDerivedA() { throw Exception("Not an A"); }
virtual DerivedB* AsDerivedB() { throw Exception("Not a B"); }
// etc.
};
class DerivedA : public Base
{
public:
DerivedA* AsDerivedA() { return this; }
};
// etc.
Use is then BasePtr->AsDerivedA()->DerivedAOnlyMethod(). Imho, this clutters up the base class, and exposes knowledge about the derived classes it shouldn't need.
I'm too inexperienced to say with certainty which is better, so I'm looking for arguments for and against either construct. Which is more idiomatic? How do they compare regarding performance and safety?
Well, putting the AsDerived#-methods into the base-class certainly leads to potentially faster casting.
If you cap the inheritance-hierarchy using final that advantage might be reduced or removed though.
Also, you are right about it being uncommon because it introduces clutter, and it introduces knowledge of all relevant derived classes into the base-class.
In summary, it might sometimes be useful in a bottleneck, but you will pay for that abomination.
Without seeing more code it is difficult to offer too much advice. However, needing to know the type of the object you're calling into argues more for a variant than a polymorphic type.
polymorphism is about information hiding. The caller should not need to know what type he is holding.
something like this, perhaps?
struct base
{
virtual bool can_do_x() const { return false; }
virtual void do_x() { throw std::runtime_error("can't"); }
virtual ~base() = default;
};
struct derived_a : base
{
virtual bool can_do_x() const { return true; }
virtual void do_x() { std::cout << "no problem!"; }
};
int main()
{
std::unique_ptr<base> p = std::make_unique<derived_a>();
if (p->can_do_x()) {
p->do_x();
}
}
Now we're talking to the object in terms of capabilities, not types.
Your intuition is right, the AsDerivedX methods are clutter. The fact that at runtime it can be checked whether these virtual functions were overloaded is equivalent to the cost of a typecheck. So, in my opinion, the C++ way of doing this is:
void doSomething(Base *unsureWhichAorB) {
DerivedA *dA = dynamic_cast<DerivedA*>(unsureWhichAorB);
if(dA) //if the dynamic cast failed, then dA would be 0
dA->DerivedAOnlyMethod();
}
Note that the check for non-zeroness of dA is critical here.
You are totally correct that such a solution not only clutters the base class but also puts unnecessary dependencies on it. In a clean design the base class does not need to and actually should not know anything about its derived classes. Everything else will become a maintenance nightmare pretty soon.
However, I'd like to point out that I am in the "try to avoid dynamic_cast"-Team. Meaning that I often see dynamic_cast that could have been avoided with a proper design. So the question to ask in the first place would be: Why do I need to know the derived type? Usually there is either a way to solve the problem by using polymorphism correctly or "losing" the type information already was the wrong path.
Prefer to use polymorphism instead of dynamic_cast:
class Base
{
public:
virtual void doSomething() = 0;
};
class DerivedA : public Base
{
public:
void doSomething() override { //do something the DerivedA-way };
};
class DerivedB : public Base
{
public:
void doSomething() override { //do something the DerivedB-way };
};
// etc.

C++ Vastly Different Derived Classes - Virtual methods? A cast?

I have a class hierarchy with lots of shared member functions in a base class, and also a large number of unique member functions in two derived classes:
class Scene {
public:
void Display();
void CreateDefaultShapes();
void AddShape(Shape myShape);
// lots more shared member functions
}
Class AnimatedScene : public Scene {
public:
void SetupAnimation();
void ChangeAnimationSpeed(float x, float y);
// lots of member functions unique to animation
}
Class ControllableScene : public Scene {
public:
void ConfigureControls();
void MoveCamera(float x, float y, float z);
void Rotate(float x, float y, float z);
// lots of member functions unique to a controllable scene
}
Not surprisingly, this doesn't work:
Scene myScene;
myScene.SetupAnimation();
What is the correct solution to this problem? Should I make all of the derived member functions virtual and add them to the base? Should I use a cast when calling SetupAnimation()? Is there a more clever design that solves this problem?
Note: I receive myScene from elsewhere and can't simply declare it as AnimatedScene when I instantiate it.
Edit: I've added a couple more member functions to illustrate the point. A small handful of initialization functions definitely lend themselves to simply using virtual.
You can cast it, preferably using static_cast. The least preferable option. If you are casting things, it usually means your design needs more thought
If you have a particular function/class that needs one or the other, declare the input as the type you need, which more accurately communicates the requirements of the function or class
If the function needs to be generic, and those methods don't require any input, then you could define a virtual method in the parent class, say init, which in the derived classes call the correct methods to set up the instance.
I have a similar problem in my compiler project, where the AST (Abstract Syntax Tree) is constructed from the statements, so while(x != 0) { if (a == b) x = 0; } would construct a whileAST with a binaryExpr inside it, then a blockAST with the ifAST, and so on. Each of these have some common properties, and a lot of things that only apply when you actually do something specific to that part. Most of the time, that is solved by calling a generic (virtual) member function.
However, SOMETIMES you need to do very specific things. There are two ways to do that:
use dynamic_cast (or typeid + reinterpret_cast or static cast).
Set up dozens of virtual member functions, which mostly are completely useless (doesn't do anything or return an "can't do that" indication of some sort)
In my case, I choose the first one. It shouldn't be the common case, but sometimes it is indeed the right thing to do.
So in this case, you'd do something like:
AnimatedScene *animScene = dynamic_cast<AnimatedScene*>(&scene);
if (!animScene)
{
... do something else, since it's not an AnimatedScene ...
}
animScene->SetupAnimation();
I am not yet able to comment, which is what I really wanted to do, but I am also interested in figuring this out as well.
A few months ago I had a similar problem. What I can tell you is that you can use typeid operator to figure out what type the object is, like so:
int main()
{
scene* ptr = new AnimatedScene();
if (typeid(*ptr) == typeid(AnimatedScene))
{
cout<<"ptr is indeed a animatedScene"<<endl;
AnimatedScene* ptr2 = (AnimatedScene*)(ptr);
ptr2->SetupAnimation();
}
else
{
cout<<"not a animatedscene!!!"<<endl;
}
}
This works, you'll then be able to use ptr2 to access the animatedScene's unique members.
Notice the use of pointers, you can't use the objects directly, due to something called "object slicing" when playing with polymorphism: https://en.wikipedia.org/wiki/Object_slicing
Like you I have heard something about the use of typeid and thus, casting being a bad idea, but as to why, I cannot tell you. I am hoping to have a more experienced programmer explain it.
What I can tell you is that this works without problems in this simple example, you've avoided the problem of declaring meaningless virtual functions in the basetype.
Edit: It's amazing how often I forget to use google: Why is usage of the typeid keyword bad design?
If I understand mr Bolas correctly, typeid incentivizes bad coding practices. However, in your example you want to access a subtypes non-virtual function. As far as I know, there is no way of doing that without checking type at compiletime, ie typeid.
If such problem arises with your hierarchy that proves that hierarchy was too generalized. You might want to implement interfaces pattern, if class have certain functionality, it would inherit an interface that defines that functionality.
Proven that dogs are animals, do all animal but dogs fail to bark, or do only dogs bark?
The first approach lead to a class animal failing all the verses of the entire zoo, implemented one-by one in each animal. And in particular class dog will override just bark().
In this approach animal becomes a sort of "god object" (knows everything), requiring to be constantly updated every time something new is introduced, and requiring It's entire "universe" to be re-created (recompile everything) after it.
The second approach requires first to check the animal is a dog (via dynamic cast) and then ask it to bark. (or check for cat before asking a mieow)
The trade-off will probably consist in understanding how frequent is the possibility you have to check a bark out of its context (not knowing which animal are you deal with), how to report a fail, and what to do in case of such fail.
In other words, the key driver is not the bark, but the context around it inside your program.
//Are you trying to do something like this?
class Scene{
public:
virtual void Display()=0; //Pure virtual func
};
class AnimatedScene : public Scene{
public:
void Display(){
std::cout<<"function Display() inside class AnimatedScene" <<std::endl;
}
};
class ControllableScene : public Scene{
public:
void Display(){
std::cout<<"function Display() inside class ControllableScene" <<std::endl;
}
};
int main(){
AnimatedScene as;
ControllableScene cs;
Scene *ex1 = &as;
Scene *ex2 = &cs;
ex1->Display();
ex2->Display();
return 0;
}

Compile time check whether a base class is "interface"

After it turned out that what I originally wanted is probably not possible w/o involving C++11 I want to slightly change the requirement and ask you if this can be achieved.
previous question
Basically I want to check in compile time if a class is inheriting from "interface". By interface I mean class with pure virtual methods only.
I would like to do the following code:
template <typename T>
class Impl : public T {
public:
STATIC_ASSERT_INTERFACE(T);
};
The behavior here is if T has only pure virtual methods then it will compile and if one of its methods is not then fail.
Can anyone think of something like that?
This is basically similar to Java interfaces. In C++, there is no existence of interface as such, it's just a terminology used for a class with all pure-virtual methods and only static const data members.
Additionally, pure virtual methods may or may not have a function body. Thus C++ pure virtual methods are not exactly same as Java's abstract methods.
Unfortunately what you are asking is not possible to simulate in C++.
First off, interfaces are not really a native concept to C++. I'm sure most programmers know what they are, but the compiler doesn't, and that's where you're running into problems. C++ can do a lot of things, and I bet you can twist it into looking like a lot of different languages, but if you're going to write C++, it's best to do things the C++ way.
Another thing - there's a lot of grey area here. What if you had an "interface" like you suggested, but somebody did one of these:
// Technically not a member function, but still changes the behavior of that class.
bool operator==(const Interface &left, const Interface &right);
I'm almost 100% sure you can't stop someone from doing that.
You may be able to make sure there are no member variables though, even though I'm not sure I agree with this way of doing things. Make an empty class, and then do a static_assert(sizeof(InterfaceClass) == sizeof(Empty)). I'm not sure if it's safe to assume the size would be 0 - that's a question for someone more familiar with the standards.
What you want can not be done directly, as others have already explained.
However, you can still get the behavior you want with a bit of discipline from the interface developers. If all your interfaces derive from a common base class Interface, you can check that Interface is a base class at compile time using a technique similar to this question.
For example :
class Interface {
public :
virtual ~Interface() { }
};
template <typename T>
struct IsDerivedFromInterface {
static T t();
static char check(const Interface&);
static char (&check(...))[2];
enum { valid = (sizeof(check(t())) == 1) };
};
class MyInterface : public Interface {
public :
virtual void foo() = 0;
};
class MyBase {
public :
virtual void bar() { }
};
class Foo : public MyInterface {
public :
virtual void foo() { }
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Foo>::valid); // just fine
class Bar : public MyBase {
public :
virtual void bar() { }
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Bar>::valid); // oops
Of course, the developer of the base class can cheat and derive from Interface even though the base class is not an interface. Which is why I said it requires some discipline from the developer.
That said though, I can't see how this would be useful. I've never felt I needed this kind of compile time check.

What's the usage if I provide an implementation for a pure virtual function in C++

I know that it's OK for a pure virtual function to have an implementation. However, why it is like this? Is there conflict for the two concepts? What's the usage? Can any one offer any example?
In Effective C++, Scott Meyers gives the example that it is useful when you are reusing code through inheritance. He starts with this:
struct Airplane {
virtual void fly() {
// fly the plane
}
...
};
struct ModelA : Airplane { ... };
struct ModelB : Airplane { ... };
Now, ModelA and ModelB are flown the same way, and that's believed to be a common way to fly a plane, so the code is in the base class. However, not all planes are flown that way, and we intend planes to be polymorphic, so it's virtual.
Now we add ModelC, which must be flown differently, but we make a mistake:
struct ModelC : Airplane { ... (no fly function) };
Oops. ModelC is going to crash. Meyers would prefer the compiler to warn us of our mistake.
So, he makes fly pure virtual in Airplane with an implementation, and then in ModelA and ModelB, put:
void fly() { Airplane::fly(); }
Now unless we explictly state in our derived class that we want the default flying behaviour, we don't get it. So instead of just the documentation telling us all the things we need to check about our new model of plane, the compiler tells us too.
This does the job, but I think it's a bit weak. Ideally we instead have a BoringlyFlyable mixin containing the default implementation of fly, and reuse code that way, rather than putting code in a base class that assumes certain things about airplanes which are not requirements of airplanes. But that requires CRTP if the fly function actually does anything significant:
#include <iostream>
struct Wings {
void flap() { std::cout << "flapping\n"; }
};
struct Airplane {
Wings wings;
virtual void fly() = 0;
};
template <typename T>
struct BoringlyFlyable {
void fly() {
// planes fly by flapping their wings, right? Same as birds?
// (This code may need tweaking after consulting the domain expert)
static_cast<T*>(this)->wings.flap();
}
};
struct PlaneA : Airplane, BoringlyFlyable<PlaneA> {
void fly() { BoringlyFlyable<PlaneA>::fly(); }
};
int main() {
PlaneA p;
p.fly();
}
When PlaneA declares inheritance from BoringlyFlyable, it is asserting via interface that it is valid to fly it in the default way. Note that BoringlyFlyable could define pure virtual functions of its own: perhaps getWings would be a good abstraction. But since it's a template it doesn't have to.
I've a feeling that this pattern can replace all cases where you would have provided a pure virtual function with an implementation - the implementation can instead go in a mixin, which classes can inherit if they want it. But I can't immediately prove that (for instance if Airplane::fly uses private members then it requires considerable redesign to do it this way), and arguably CRTP is a bit high-powered for the beginner anyway. Also it's slightly more code that doesn't actually add functionality or type safety, it just makes explicit what is already implicit in Meyer's design, that some things can fly just by flapping their wings whereas others need to do other stuff instead. So my version is by no means a total shoo-in.
Was addressed in GotW #31. Summary:
There are three main reasons you might
do this. #1 is commonplace, #2 is
pretty rare, and #3 is a workaround
used occasionally by advanced
programmers working with weaker
compilers.
Most programmers should only ever use #1.
... Which is for pure virtual destructors.
There is no conflict with the two concepts, although they are rarely used together (as OO purists can't reconcile it, but that's beyond the scope of this question/answer).
The idea is that the pure virtual function is given an implementation while at the same time forcing subclasses to override that implementation. The subclasses may invoke the base class function to provide some default behavior. The base cannot be instantiated (it is "abstract") because the virtual function(s) is pure even though it may have an implementation.
Wikipedia sums this up pretty well:
Although pure virtual methods
typically have no implementation in
the class that declares them, pure
virtual methods in C++ are permitted
to contain an implementation in their
declaring class, providing fallback or
default behaviour that a derived class
can delegate to if appropriate.
Typically you don't need to provide base class implementations for pure virtuals. But there is one exception: pure virtual destructors. In fact if your base class has a pure virtual destructor, it must have an implementation. Why would you need a pure virtual destructor instead of just a virtual one? Typically, in order to make a base class abstract without requiring the implementation of any other method. For example, in a class where you might reasonably use the default implementation for any method, but you still don't want people to instantiate the base class, you can mark only the destructor as pure virtual.
EDIT:
Here's some code that illustrates a few ways to call the base implementation:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0;
};
class Der : public Base
{
public:
void DoIt();
};
void Base::DoIt()
{
cout << "Base" << endl;
}
void Der::DoIt()
{
cout << "Der" << endl;
Base::DoIt();
}
int main()
{
Der d;
Base* b = &d;
d.DoIt();
b->DoIt(); // note that Der::DoIt is still called
b->Base::DoIt();
return 0;
}
That way you can provide a working implementation but still require the child class implementer to explicitely call that implementation.
Well, we have some great answers already.. I'm to slow at writing..
My thought would be for instance an init function that has try{} catch{}, meaning it shouldn't be placed in a constructor:
class A {
public:
virtual bool init() = 0 {
... // initiate stuff that couldn't be made in constructor
}
};
class B : public A{
public:
bool init(){
...
A::init();
}
};