openMSX
utils
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
39
template
<
typename
T>
int
checkInvalidOuterUsage
(T) {
return
0; }
40
41
#define OUTER(type, member) (checkInvalidOuterUsage<const decltype(std::declval<type&>().member)*>(this), \
42
*reinterpret_cast<type*>(reinterpret_cast<uintptr_t>(this) - offsetof(type, member)))
43
44
#endif
checkInvalidOuterUsage
int checkInvalidOuterUsage(T)
Definition:
outer.hh:39
Generated on Thu Dec 7 2023 21:13:26 for openMSX by
1.9.4