Is there a safe navigation operator for C++?

Viewed 1850

In Modern C++, is there a way to do safe navigation?

For example, instead of doing...

if (p && p->q && p->q->r)
    p->q->r->DoSomething();

...having a succinct syntax by using some sort of short-circuiting smart pointer, or some other kind of syntax leveraging operator overloading, or something in the Standard C++ Library, or in Boost.

p?->q?->r?->DoSomething(); // C++ pseudo-code.

Context is C++17 in particular.

3 Answers

although it's 2022 now, there's still no language level support for this. a very close simulation I can figure out:

template <typename T, typename F>
auto operator->*(T&& t, F&& f) {
  return f(std::forward<T>(t));
}

#define pcall(fn)                                                            \
  [&](auto&& __p) {                                                          \
    if constexpr (std::is_pointer_v<std::remove_reference_t<decltype(__p)>>) \
      return __p ? __p->fn : decltype(__p->fn){};                            \
    else                                                                     \
      return __p ? __p.fn : decltype(__p.fn){};                              \
  }

struct A {
  int v;
  int foo(int a, int b) { return a + b + v; }
};
struct B {
  A* getA() { return &a; }
  A a{100};
};
struct C {
  B* getB() { return &b; }
  B b;
  operator bool() { return true; }
};

int main(){
    int v = 3;

    C by_val;
    int t1 = by_val->*pcall(getB())->*pcall(getA())->*pcall(foo(1, v));

    C* by_ptr = &by_val;
    int t2 = by_ptr->*pcall(getB())->*pcall(getA())->*pcall(foo(1, v));
}

https://godbolt.org/z/zPhzTTv9s

Related