STD::Optional in C++: A Guide

std::optional is a feature in C++ that can distinguish optional values in a type-safe manner to make code more readable and consistent. Learn more.

Written by Swastik Baranwal
Published on Sep. 05, 2024
Developer writing code in C++ and using stdoptional
Image: Shutterstock / Built In
Brand Studio Logo

std::optional is a feature introduced in C++ 17 to represent optional values. It can distinguish the possibility of having a value or not having a value in a type-safe manner.

What Is STD::Optional in C++?

std::optional in C++ is used to represent optional values in a type-safe manner. It’s useful for tasks like dividing two numbers, error handling and changing the default value. It’s syntax is:

std::optional<T> opt_var;

For example, there are times when you want to return a potential value like NULL or an error to indicate a problem.

int check_name(std::string name) {
     if (name == "Tom")
         return 0;
     else
         return -1; //  Used to indicate invalid input 
}

When calling this function, one would have to check if -1 is returned or not according to the input.

code = check_name("Same")
if (code == -1) {
    ...
}

This can make your code unreadable and inconsistent if other values are returned in rest functions. That’s where std::optional comes to the rescue.

 

STD::Optional Syntax

The syntax for std::optional is as follows:

std::optional<T> opt_var;

In the above code, T represents the optional value to be stored. There are three primary methods:

  1. has_value: Checks whether the object contains a value.
  2. value: Returns the contained value.
  3. value_or: Returns the contained value if available, or another value otherwise.

More on Software EngineeringC++ Basics: Understanding Lambda

 

How to Use STD::Optional

Below are three common examples for how you can use std::optional, with code.

1. Dividing Two Numbers

To check if one number can divide another number or not:

#include <iostream>
#include <optional>

std::optional<int> divide(int num1, int num2) {
    if (num2 != 0) {
        return num1/num2;
    }
    return std::nullopt; // Indicates no type-safe value
}

int main() {
    auto result = divide(10, 2); // To infer into std::optional<int>, used to save time 
    if (result.has_value()) {  // has_value checks if a type-value is returned
        std::cout << "Result: " << result.value() << std::endl; // value returns the value as function arguments are correct
    } else {
        std::cout << "Division by zero" << std::endl;
    }

    return 0;
}

2. Error Handling

std::optional can also be used to simplify error handling when you want to read a file, parse strings then convert them into integers and format them.

#include <iostream>
#include <fstream>
#include <optional>
#include <string>

std::optional<std::string> try_reading_file(const std::string& filename) { // const to make sure it doesn't get modified
    std::ifstream file(filename); // std::ifstream for reading files 
    if (!file.is_open()) {  // if file cannot be opened
        return std::nullopt;
    }

    std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); //Written the content inside the file
    return content;
}

int main() {
    const std::string filename = "exmpl.txt";

    // try to read the file
    auto fileContent = try_reading_file(filename);

    if (fileContent.has_value()) {
        std::cout << "File content:\n" << fileContent.value() << std::endl;
    } else {
        std::cerr << "Error: Could not open the file " << filename << std::endl;
    }

    return 0;
}

3. Changing the Default Value

Finally, std::optional can be used to check and change the default value:

#include <optional>
#include <iostream>

int main() {
    std::optional<int> value;

    int result = value.value_or(42);  // Assigns 42 if value is not present

    std::cout << "Result: " << result << std::endl;

    return 0;
}

These are the most common usages of std::optional.

 

STD::Optional in Other Programming Languages

  • Rust has an Option enum to implement optionals.
  • Go doesn’t have optional so it uses a type called error for error handling.
  • Java also implements optional via generics/classes.
  • V implements option for returning optional values and result for resultant values.
A tutorial on how to use std::optional in C++. | Video: C++ Weekly With Jason Turner

More on Software EngineeringCode First Approach vs. Database First Approach: Which Is Best?

 

When to Use STD::Optional

Whenever you have to denote an answer or value-or-not-value, it’s recommended to use std::optional, unless you are working with legacy code where integers are used. It also increases the capacity to describe complex problems, readability and handle errors.

Frequently Asked Questions

std::optional is a feature in C++ that can be used to represent optional values. Its syntax is as follows:

std::optional<T> opt_var;

You can use std::optional for a variety of tasks, including dividing two numbers, handling errors and changing the default value. There are three main methods to use it:

  • has_value: Checks whether the object contains a value
  • value: Returns the contained value
  • value_or: Returns the contained value if available, another value otherwise

std::optional should be used when you need to denote whether something is a value or not a value. For example, you’d use std::optional if you want to denote NULL or an error to indicate a problem. 

Explore Job Matches.