/** * Nonempty base class */ struct Base { int v; void do_something(); static void do_something(Base* self); }; /** * Child class that introduces a vtable pointer * * The combination of nonempty base and vtable in child causes an offset * between pointers to Base and pointers to Child. * * Example: * Child* child = NOT NULL; * Base* base = child; * reinterpret_cast(child) != reinterpret_cast(base); */ struct Child: Base { virtual ~Child() = default; Base* self_as_base(); }; /** * Unconditional conversion because `this` must not be NULL */ Base* Child::self_as_base() { return this; } /** * Conditional conversion because child may be NULL */ Base* child_to_base_ptr(Child* child) { return child; } /** * Unconditional conversion because references must not be NULL */ Base& child_to_base_ref(Child& child) { return child; } /** * Unconditional conversion because `this` must not be NULL */ void call_do_something(Child** children, int count) { for(int i = 0; i < count; ++i) children[i]->do_something(); } /** * Conditional conversion because child may be NULL */ void call_do_something_static_ptr(Child** children, int count) { for(int i = 0; i < count; ++i) Base::do_something(children[i]); } /** * Unconditional conversion because references must not be NULL */ void call_do_something_static_ref(Child** children, int count) { for(int i = 0; i < count; ++i) Base::do_something(&static_cast(*children[i])); }