I looked several online std::optional documentary over the internet. However I could not be able to find any direct comparison between two cases below:
case 1:
SomePointer* foo::get_some_pointer(cont int value) {
auto result = myMap.find(value);
if (result != myMap.end()) {
return const_cast<SomePointer*>(&result->second);
}
return nullptr;
}
case 2
std::optional<SomePointer*> foo::get_some_pointer (cont int value) {
auto result = myMap.find(value);
if (result != myMap.end()) {
return std::optional<SomePointer*>{&result->second};
}
return std::nullopt;
}
What are the advantages/disadvantages of the case 1 over the case 2(nullopt over nullptr) ?
The sole job of std::optional
is to extend the type domain by an additional "null" value. Every pointer type T*
already has a value considered "null" - nulltpr
.
Thus, it's not a good idea to compare those two directly, because they answer different questions. Sometimes it's important to differentiate between "no result" and "null result"1 (which is one of the possible interpretations), sometimes it's not. You should use whichever fits your needs.
Now if the only reason the code returned a pointer was to make use of the implicit pointer nullability, then the proper solution would be to change it to return std::optional<SomePointer>
(or perhaps std::optional<std::reference_wrapper<SomePointer>>
) instead, but that's not what you asked about.
1 Of course at this point it's also worthwhile to consider something like e.g. struct NoResult {}; using Result = std::variant<NoResult, SomePointer*>;
to make it even more explicit.