Suppose I have class with no data:
struct Empty {
/*some methods here*/
};
And a derived class
struct Derived: Empty {
int a;
int b;
char c;
....
}__attribute__((packed));`
Objects of Empty class have size = 1. Empty part of derived class usually has 0 size. As I understand compiler see that base Empty class has no data so it can optimize size of Empty in case it is "inside" Derived but it is not required to do it by the standard.
So the question is:
Can I somehow determine at compile time that Empty part of Derived class doesn't really occupy memory.
I understand that I can do check like sizeof(Derived) = sizeof(a) + sizeof(b) ...
But It is too verbose and there are several classes like Derived. Is there more elegant solution?
You can use std::is_empty
to make sure that the class you're inheriting from is zero-sized:
static_assert(std::is_empty<Empty>{});
If it is, empty base optimization is guaranteed to take place for standard-layout classes.
I understand that I can do check like
sizeof(Derived) = sizeof(a) + sizeof(b) ...
But It is too verbose. Is there more elegant solution?
This does not work properly because you need to take padding into account and eventual attributes such as packed
.
You can use more "old" (before C++11) macro - offsetof:
struct Empty {};
struct NonEmpty {
int a;
};
struct Derived1: Empty {
int a;
int b;
char c;
};
struct Derived2: NonEmpty {
int a;
int b;
char c;
};
static_assert(offsetof(Derived1,a) == 0,"");
static_assert(offsetof(Derived2,a) != 0,"");
You can use this macro to check order of your member variables too:
static_assert(offsetof(Derived,a) < offsetof(Derived,b),"");
static_assert(offsetof(Derived,b) < offsetof(Derived,c),"");
But do not forget - offsetof has the same limitation:
If type is not a standard layout type, the behavior is undefined. If member is a static member or a member function, the behavior is undefined.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With