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

114 views Asked by At

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.

1

There are 1 answers

4
Mooing Duck On

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()  {  };
};