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::optionalcomes 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::optionalonly when absolutely needed
I'm leaning towards:
Use
std::optionalalways 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.
std::optionalmay be a reasonable choice. The only drawback would be that upon success you will be always creating a new object rather than reusing existing object passed as argument. This may result in significant performance penalty.std::variant<RetType, ErrorType>if you want to know the reason of error.