Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile-time Base class pointer offset to Derive class

Tags:

c++

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?

like image 605
etnlGD Avatar asked Sep 28 '13 08:09

etnlGD


1 Answers

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 .

like image 115
Sean Boocock Avatar answered Nov 22 '22 05:11

Sean Boocock