struct U;
static_assert(sizeof(void (U::*)()) == 2 * sizeof(void*) + 2 * sizeof(int), "");
struct A { int a; };
struct B { int b; };
struct I { union { struct { int a, b; }; }; };
struct S { int a, b; void f(); virtual void g(); };
struct M : A, B { int a, b; void f(); virtual void g(); };
struct V : virtual A { int a, b; void f(); virtual void g(); };
struct U { int a, b; void f(); virtual void g(); };
struct C { virtual void f(); };
struct D { virtual void g(); };
struct O : C, D { virtual void g(); };
template <typename T, int T::*F>
int ReadField(T &o) {
return F ? o.*F : 0;
}
struct V;
void ReadFields() {
A a;
I i;
S s;
M m;
V v;
U u;
ReadField<S, &S::a>(s);
ReadField<M, &M::a>(m);
ReadField<V, &V::a>(v);
ReadField<U, &U::a>(u);
ReadField<S, &S::b>(s);
ReadField<M, &M::b>(m);
ReadField<V, &V::b>(v);
ReadField<U, &U::b>(u);
ReadField<S, nullptr>(s);
ReadField<M, nullptr>(m);
ReadField<V, nullptr>(v);
ReadField<U, nullptr>(u);
ReadField<A, &A::a>(a);
ReadField<A, nullptr>(a);
ReadField<I, &I::a>(i);
ReadField<I, &I::b>(i);
}
template <typename T, void (T::*MFP)()>
void CallMethod(T &o) {
(o.*MFP)();
}
void CallMethods() {
S s;
M m;
V v;
U u;
O o;
CallMethod<S, &S::f>(s);
CallMethod<M, &M::f>(m);
CallMethod<V, &V::f>(v);
CallMethod<U, &U::f>(u);
CallMethod<S, &S::g>(s);
CallMethod<M, &M::g>(m);
CallMethod<V, &V::g>(v);
CallMethod<U, &U::g>(u);
CallMethod<O, &O::g>(o);
CallMethod<S, nullptr>(s);
CallMethod<M, nullptr>(m);
CallMethod<V, nullptr>(v);
CallMethod<U, nullptr>(u);
}
namespace NegativeNVOffset {
struct A {};
struct B : virtual A {};
struct C : B {
virtual void f();
};
}
template void CallMethod<NegativeNVOffset::C, &NegativeNVOffset::C::f>(NegativeNVOffset::C &);