An optional<T> has two states: it either holds a T or nothing. There's no third state.
All pointers can be null, but unlike (for example) Java, we don't have to deal with pointers to objects all the time. C++ has value types and it's perfectly possible to pass objects that cannot be null.
#include <cstdio>
using namespace std;
class Type {
public:
Type(int a):_a(a){};
int _a;
};
Type& getType(int a) {
Type* t = NULL;
t = new Type(a);
return (*t);
}
Type& doSthWith(Type& t) {
//no need (and no way) to check if t is reference to proper object
t._a=t._a+1;
return t;
}
int main() {
Type& t = doSthWith(getType(5));
printf("%d\n",t._a);
return 0;
};
This can be broken of course, for example by
Type& getType(int a) {
Type* t = NULL;
return (*t);
}
Right. What makes Haskell special is not that it has option types, it's the fact that most types in Haskell cannot be null. This allows us to write pure (and total) functions, knowing that the compiler will enforce it; giving us a high degree of assurance that our function will not fail.
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 :-)
You have an option type in Guava as well, but compared to Haskell, it's annoying to use due to the lack of pattern matching. Also, you can't magically chain them the way you can do with Maybe.
All pointers can be null, but unlike (for example) Java, we don't have to deal with pointers to objects all the time. C++ has value types and it's perfectly possible to pass objects that cannot be null.