How std::optional
fits in my code?
My code contains MANY functions that looks roughly like:
bool GetName(_Out_ string& strRes)
{
// try to get/calculate the value
// value may also be empty
// return true on success, false otherwise.
}
Now that I have found out std::optional, I simply code:
std::optional<std::string> GetName()
Why or when not to use std::optional
?
- I understand that using
std::optional
comes with a performance price and for the sake of argument, let's assume I'm willing to pay it. - I also understand that coding something like:
std::optional<int> iVal = 9;
is pointless.
Am I overly charmed by std::optional
?
I find std::optional
so natural that it lead me to a conclusion that, by default, many of my native types, bool
, int
, string
, should be declared as std::optional
.
So, instead of following the premise of:
Use
std::optional
only when absolutely needed
I'm leaning towards:
Use
std::optional
always unless you are sure it isn't needed now or in the future.
Question 1
Is the following rule valid:
use std::optional
when:
- a value is calculated on run time
- calculation may fail
- you want to know if calculation failed
Question 2
If using std::optional
becomes abundant, am I risking code readability issues?
Update
Answers and comments steered the discussion a bit away from my initial concern which is an attempt to define a rule of thumb for when to use std::optional
.
I will address some of the common feedback I got:
Your are coding C-style error checking functions.
use exceptions when the calculation fails.
It is perhaps my fault for providing a not-so-good example of my motivation. GetName()
is just a taste of my common use case.
Instead of focusing on how errors are reflected (if any), I wanted to focus on is name a good candidate for optional?
I didn't state that if GetName
returns false it implies some sort of error in my flow. When GetName
return false, I could either generate a random name or just ignore the current iteration. Regardless of how the callers reacts to the return value, name
is optional
in a sense that it may not be present
.
I can provide a better example:
void GetValuesFromDB(vector<string> vecKeys, map<string,string> mapKeyValue);
in this function I'm "forced" to provide two containers since I want to distinguish between:
- key was found in DB and it is empty. this key will be in
mapKeyValue
- key was not found in DB. . this key will NOT be in
mapKeyValue
But with optional
I could go:
void GetValuesFromDB(map<string,std::optional<string> > mapKeyValue);
I believe that we're taking the word optional
too literally.
I really support the notion that one may use std::optional
If you want to represent a nullable type nicely. Rather than using unique values (like -1, nullptr, NO_VALUE or something)
The c++ standard committee could have easily decided to name std::optional
, std::nullable
.