Here is a fixed version of Romeo's suggestion:
template <typename X0>
auto safe_chain(X0* x0)
{
return x0;
}
template <typename X0, typename X1, typename... Xs>
auto safe_chain(X0* x0, X1 x1, Xs... xs)
{
return x0
? safe_chain(x0->*x1, xs...)
: nullptr;
}
// usage
struct C {
void DoYerThing();
};
struct B {
C* pC;
};
struct A {
B* pB;
};
if(auto p = safe_chain(pA, &A::pB, &B::pC))
p->DoYerThing();
This isn't exactly easy to read. pA && pA->pB && pA->pB->pC
is just fine.
The idiomatic solution is usually to rely on references whenever possible, so that null pointer checks are limited to as few as possible. When a pointer is really needed, you should use a function (possibly a member function of *pA
) to avoid duplicating the checks.