Search code examples
c++c++11inheritancesizeofdecltype

sizeof(*this) and decltype(*this) in derived classes


Suppose there are classes:

struct A {
  int a;

  virtual size_t GetMemoryUsage() const {
    return sizeof(*this);
  }
};

struct B : public A {
  int b;
};

And there may be deeper inheritance.

What I want is to have a method which will return the number of bytes an object occupies in memory, GetMemoryUsage() in this case. Usually it can be achieved by using sizeof(*this). The problem is (at least AFAIU) that I have to override the method in each derived class and actually copy-paste its body. I don't like duplicated code :)

Am I correct? How can I make sizeof(*this) and decltype(*this) return what I want in subclasses, by calling them only from base class's methods? Is there a more elegant solution?


Solution

  • You do not have to implement GetMemoryUsage for each of your derived classes manually, just leave it as pure virtual. E.g.:

    struct A
    {
        virtual ~A() = default;
        virtual size_t GetMemoryUsage() const noexcept = 0;
    };
    
    struct B : A
    {
        int b;
    };
    

    When creating objects, however, that function must be implemented. You can do that using a factory function that "decorates" the class with a generic implementation of that pure virtual:

    // Can alternatively be defined inside function template create.
    template<class T>
    struct GetMemoryUsageImpl : T
    {
        using T::T;
        size_t GetMemoryUsage() const noexcept final {
            return sizeof(T);
        }
    };
    
    template<class T, class... Args>
    std::unique_ptr<T> create(Args&&... args) {
        return std::unique_ptr<T>(new GetMemoryUsageImpl<T>(std::forward<Args>(args)...));
    }
    

    Usage:

    void f(A& a) {
        auto object_size = a.GetMemoryUsage();
    }
    
    int main() {
        auto b = create<B>();
        f(*b);
    }
    

    You can also implement a hierarchy of interfaces incrementally easily using this idiom.