If we choose to write optional<User*>, then we have three possibilities. The point is that we don't have to do that in C++, we can write optional<User> and be certain that the returned value is either empty or a User.
Compare this with a function that returns a string:
string get_name();
In C++, the caller of this function knows that a string is always returned. Null isn't part of the picture. The string object itself holds a pointer to some heap data, but that's not something the user has to deal with.
PS: I've done my fair share of programming in Haskell so I know the advantages it has :-)