class Base1 {
int x;
};
class Base2 {
int y;
};
class Derive : public Base1, public Base2 {
public:
enum {
PTR_OFFSET = ((int) (Base2*)(Derive*)1) - 1,
};
};
But the compiler complains
expected constant expression
Everyone knows that the expression values 4 except the compiler, what goes wrong?
How, then, to get the offset at compile time?
Addressing the immediate compiler error you are seeing in the supplied code, (Base2*)(Derive*)1
will most likely become reinterpret_casts when compiled, and that as DyP wrote as a comment to the question is not a constant expression which is required for enumeration initialization. Some compilers, notably GCC are not as strict on this point and will allow for reinterpret_cast in constant expressions even though it is forbidden by the standard (for further discussion of this see the comments for this GCC bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49171 and Constexpr pointer value).
The broader question of identifying at compile time what the layout of an object is and the offsets to its various members is a tricky one without a well-defined answer. The standard give implementers a lot of latitude to pad/pack an object's fields, usually out of alignment considerations (for a good summary see http://www.altdevblogaday.com/2013/05/03/cc-low-level-curriculum-part-11-inheritance/). While the relative ordering of an object's field must be maintained, int y
in an instance of Derived
need not be at an offset of sizeof(x)
from the start of the instance of Derived
; the answer is compiler and target architecture dependent.
All of that being said, this sort of structure layout information is determined at compile time and at least on some compilers is made accessible (even if not in portable, standards compliant ways). In the answer to this question, C++ Compile-Time offsetof inside a template, Jesse Good provides some code that on GCC at least will allow one to determine field offsets within a type at compile time. This code will unfortunately not provide the correct offsets for base class members.
A good solution to your problem awaits implementation of compile time reflection support in C++, something for which there is ongoing work as part of a standards working group: https://groups.google.com/a/isocpp.org/forum/#!forum/reflection .
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