openMSX
outer.hh
Go to the documentation of this file.
1 #ifndef OUTER_HH
2 #define OUTER_HH
3 
4 #include <cstddef>
5 
6 // Example usage:
7 // class Foo {
8 // ...
9 // struct Bar : public SomeBaseClass {
10 // ...
11 // void f() override {
12 // // transform the 'this' pointer to the 'bar' inner object
13 // // into a reference to the outer object of type Foo.
14 // Foo& foo = OUTER(Foo, bar);
15 // }
16 // } bar;
17 // };
18 //
19 // This avoids having to store a back-pointer from the inner 'bar' object to
20 // the outer 'Foo' object.
21 //
22 // The 'bar' object lives at a fixed offset inside the 'Foo' object, so
23 // changing the bar-this-pointer into a Foo-reference is a matter of
24 // subtracting this (compile-time-constant) offset.
25 //
26 // At least the offset is constant in the absence of virtual inheritance (we
27 // don't use this c++ feature in openMSX). Also strictly speaking the c++
28 // standard doesn't guarantee the offset is constant in the presence of virtual
29 // functions, though it is in all practical implementations. See here for more
30 // background info:
31 // http://stackoverflow.com/questions/1129894/why-cant-you-use-offsetof-on-non-pod-structures-in-c
32 
33 
34 // Adjust the current 'this' pointer (pointer to the inner object) to a
35 // reference to the outer object. The first parameter is the type of the outer
36 // object, the second parameter is the name of the 'this' member variable in
37 // the outer object.
38 #define OUTER(type, member) *reinterpret_cast<type*>(reinterpret_cast<uintptr_t>(this) - offsetof(type, member));
39 
40 #endif