What would you do if value_at returned a T*? You can't do value_or() on a T*, because pointers have very few operations you can do on them (and nearly all of those would be straight up invalid in this use-case - which does not make for a great API!) you'd either push for some language feature that does that or you'd write some non-member function that handles this case. Which would be fine for value_or(), but not for any number of other operations that work for optional but not for pointers. What if you wanted the size of the span there, or 0?
With optional, these things just compose straightforwardly, so: m.value_at(p).transform(ranges::size).value_or(0)
How do you do that with a pointer?
Note that neither of these examples work with optional<reference_wrapper<T>> either.