T*
doesn't have any member functions, whereas optional<not_null<T*>>
has a bunch.
What I'd like is to be able to compose functions like
auto result = maybe_A()
.transform(A_to_B)
.and_then(B_to_opt_C)
.or_else({});
which should be equivalent to
optional<A&> first = maybe_A();
optional<B&> second = first.transform(A_to_B);
optional<C&> third = second.and_then(B_to_opt_C);
C result = third.or_else({});
With pointers, we can't do that as one expression.
A* first = maybe_A();
B* second = first ? A_to_B(*first) : nullptr;
C* third = second ? B_to_opt_C(*second) : nullptr;
C result = third ? *third : {};
Whereas at least with optional<not_null<T*>>
we can adapt our functions
optional<not_null<A*>> first = maybe_A();
optional<not_null<B*>> second = first.transform([](not_null<A*> a){ return &A_to_B(*a); });
optional<not_null<C*>> third = second.and_then([](not_null<B*> b){ return B_to_opt_C(*b); });
C result = third.or_else({});
a.k.a
auto result = maybe_A()
.transform([](not_null<A*> a){ return &A_to_B(*a); })
.and_then([](not_null<B*> b){ return B_to_opt_C(*b); })
.or_else({});
optional<T&>
byT*
has the disadvantage thatT*
is not meaningful, it could be owning or not, it might be a single object or an array. :-/ – Rampant