2

If I have a derived class with multiple bases, each this pointer for each base will be different from that of the derived object's this pointer, except for one. Given two types in an inheritance hierarchy, I'd like to detect at compile time whether they share the same this pointer. Something like this should work, but doesn't:

BOOST_STATIC_ASSERT(static_cast<Base1*>((Derived *)0xDEADBEEF) == (Derived*)0xDEADBEEF);

Because it needs to be an 'integral constant expression' and only integer casts are allowed in those according to the standard (which is stupid, because they only need compile time information if no virtual inheritance is being used). The same problem occurs trying to pass the results as integer template parameters.

The best I've been able to do is check at startup, but I need the information during compile (to get some deep template hackery to work).

Joseph Garvin
  • 20,727
  • 18
  • 94
  • 165
  • "they only need compile time information if no virtual inheritance is being used" in most/all implementations. The standard allows any non-POD cast to use runtime information. – Steve Jessop Jul 15 '09 at 15:27

6 Answers6

2

I don't know how to check what you wan't but note that your assumption is false in presence of empty base classes. Any number of them can share the same offset from the start of the object, as long as they are of different type.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
  • Thinking a little more about your problem -- and assuming that your question is about the offset of base classes and not about pointers -- I'd have though that offsetof returns a constant integral expression and so should be able to do the check if your can constraint yourself to POD. But g++ complains if I use offsetof with a derived class and I wonder what I'm missing. – AProgrammer Jul 15 '09 at 15:00
  • @AProgrammer: is the thing that you're missing, that any derived class is by definition non-POD? OP therefore cannot use only POD classes. – Steve Jessop Jul 15 '09 at 15:28
  • Oops, I looked too often at the current draft (where standard-layout which is the precondition to the use of offsetof can have non virtual base classes). – AProgrammer Jul 15 '09 at 15:45
2

I am trying to solve this exact same issue. I have an implementation that works if you know what member variable is at the beginning of the base class's layout. E.g. if member variable "x" exists at the start of each class, then the following code will work to yield the byte offset of a particular base class layout from the derived class layout: offsetof(derived, base2::x).

In the case of:
struct base1 { char x[16]; };
struct base2 { int x; };
struct derived : public base1, public base2 { int x; };
static const int my_constant = offsetof(derived, base2::x);

The compiler will properly assign "16" to my_constant on my architecture (x86_64).

The difficulty is to get "16" when you don't know what member variable is at the start of a base class's layout.

user437522
  • 5,624
  • 1
  • 16
  • 2
1

I am not even sure that this offset is a constant in the first place. Do you have normative wording suggesting otherwise?

I'd agree that a non-const offset would be bloody hard to implement in the absence of virtual inheritance, and pointless to boot. That's besides the point.

MSalters
  • 173,980
  • 10
  • 155
  • 350
1

Classes do not have a this pointer - instances of classes do, and it will be different for each instance, no matter how they are derived.

  • 1
    He's creating a fake object pointer however, and attempting to use the base-class offset assumptions that are made at compile time to infer whether it has the base class or not. He doesn't need a real object - I think it's far too implementation dependent however. – polyglot Jul 15 '09 at 14:51
1

What about using

BOOST_STATIC_ASSERT(boost::is_convertible<Derived*,Base*>::value)

as documented in the following locations...

http://www.boost.org/doc/libs/1_39_0/doc/html/boost_staticassert.html

http://www.boost.org/doc/libs/1_38_0/libs/type_traits/doc/html/boost_typetraits/reference/is_convertible.html

polyglot
  • 2,031
  • 2
  • 20
  • 28
0

I didn't realize that the compiler would insert this check at runtime, but your underlying assumption isn't entirely correct. Probably not in ways that you care about though: the compiler can use the Empty Base Class Optimization if you happen to inherit from more than one base class with sizeof(base class)==0. That would result in (base class *)(derived *)1==at least one other base class.

Like I said, this probably isn't something you would really need to care about.

MSN
  • 53,214
  • 7
  • 75
  • 105