What is std::variant in C++?

std::variant is a C++ template class introduced in the C++17 standard, offering a type-safe union. In simpler terms, it enables us to store values of different types in a single variable. Unlike traditional unions, which can only hold one type at a time, std::variant provides a safe and expressive way to work with variant types.

How to use std::variant

Using std::variant is quite straightforward. We just need to include the <variant> header in our code and then we can declare a variant using the template syntax, specifying the types it can hold.

Syntax for std::variant

std::variant is a template class that can hold values of different types. The types it can hold are specified within the angle brackets. In the example below, myVariant can hold values of Type1, Type2, or Type3.

std::variant<Type1, Type2, Type3, ...> myVariant;

Code example

Let’s look at the code below:

#include <variant>
#include <iostream>
#include <string>
int main() {
std::variant<int, double, std::string> myVariant;
// Assigning values
myVariant = 42; // int
myVariant = 3.14; // double
myVariant = "Hello, C++"; // std::string
// Accessing values
if (std::holds_alternative<int>(myVariant)) {
std::cout << "It's an integer: " << std::get<int>(myVariant) << std::endl;
} else if (std::holds_alternative<double>(myVariant)) {
std::cout << "It's a double: " << std::get<double>(myVariant) << std::endl;
} else if (std::holds_alternative<std::string>(myVariant)) {
std::cout << "It's a string: " << std::get<std::string>(myVariant) << std::endl;
}
return 0;
}
Example code of using std::variant

In the example above, myVariant can hold values of type int, double, or std::string. We can assign values and later check which type it currently holds using std::holds_alternative and retrieve the value with std::get.

Additional example methods

Let’s look at the code below:

#include <variant>
#include <iostream>
#include <string>
int main() {
std::variant<int, double, std::string> myVariant;
// Assigning values
myVariant = 42; // int
myVariant = 3.14; // double
myVariant = "Hello, C++"; // std::string
// Extract the index of the currently held type
std::cout << "Type index: " << myVariant.index() << std::endl;
// Check if the variant is valueless (has not been assigned a value)
bool isValueless = myVariant.valueless_by_exception();
std::cout << "Is valueless: " << std::boolalpha << isValueless << std::endl;
return 0;
}
Additional examples of using std::variant

Code explanation 

  • Line 14: In the code above, myVariant.index(); indicates the position of the active alternative in the variant type list.

  • Line 17: myVariant.valueless_by_exception();checks whether the variant is valueless, meaning it has not been assigned any value.

  • Line 18: std::cout << "Is valueless: " << std::boolalpha << isValueless << std::endl;prints the boolean result of whether myVariant is valueless or not. The std::boolalpha manipulator is used to print true or false instead of 1 or 0.

Why use std::variant?

std::variant provides a type-safe alternative to traditional unions, reducing the risk of runtime errors associated with type mismatches. It also facilitates code readability by explicitly specifying the types a variable can hold. This can be particularly useful in scenarios where we want to represent a choice between different types, such as in parsers, state machines, or other polymorphic scenarios.

std::variant also opens up new possibilities for handling diverse types within our programs. It promotes type safety and helps us write cleaner, more expressive code.

Copyright ©2024 Educative, Inc. All rights reserved