Quick tip: How to return std::optional from a function
Here’s a template for returning a std::optional
from a function:
#include <optional>
// Remember to compile with --std=c++17 or equivalent
std::optional<double> myOptionalFunction() {
auto myValue = /* ... */;
if(myValue.IsNull()) {
// We don't have a value
return std::nullopt; // .has_value() => false
}
// We have a value, so return the value
return myValue.AsDouble(); // .has_value() => true
}
std::nullopt
is the easy way to return no value as a std::optional
. Using this method instead of the default constructor (return std::optional<double>()
in this case) you don’t explicitly have to enter the full qualified name including template argument (optional<double>
if you use namespace std;
). It’s much easier to read and copy&paste this way.
In the last line we can just return a double (myValue.AsDouble()
in this example). Why? Because this will implicitly call the implicit constructorof std::optional<double>(const double& value)
and therefore convert your double into a std::optional<double>()
instance.
Usage example:
#include // std::optional
#include // std::cerr, std::endl
using namespace std;
std::optional myOptionalFunction() {
/* Your code goes here ! */
}
int main() {
auto myOptionalValue = myOptionalFunction;
if(myOptionalValue.has_value()) {
// Print error message
cerr << "The optional has no value!" << endl;
return;
}
// Extract the value
auto myValue = myOptionalValue.value();
/* You can do something with myValue here! */
}
Alternatively you can use std::optional<T>::value_or()
like this to give either the value or a default value:
#include <optional> // std::optional
#include <iostream> // std::cerr, std::endl
using namespace std;
std::optional<double> myOptionalFunction() {
/* Your code goes here ! */
}
int main() {
auto myOptionalValue = myOptionalFunction;
const double defaultValue = 0.0;
// Value will be 0.0 if myOptionalFunction() returned <no value>
auto myValue = myOptionalValue.value_or(defaultValue);
/* You can do something with myValue here! */
}