Unions and std::variant

How do I handle errors when using std::variant?

What are the best practices for error handling when using std::variant in C++? How do I deal with exceptions and invalid accesses?

Illustration representing computer hardware

When using std::variant, there are a few key ways to handle errors and exceptional situations:

std::bad_variant_access

This exception is thrown if you call std::get with an index or type that doesn't match the currently active variant member. To avoid this, you can:Here's an example of using std::get_if:

  • Use std::holds_alternative to check if the variant holds a specific type before trying to access it.
  • Use std::get_if, which returns a pointer to the held value if it's of the specified type, or nullptr otherwise.
  • Use std::visit with a visitor that handles all possible types.
std::variant<int, std::string> v = 42;
if (auto pint = std::get_if<int>(&v)) {
    std::cout << "int: " << *pint << '\n';
} else if (auto pstr = std::get_if<std::string>(&v)) {
    std::cout << "string: " << *pstr << '\n';
}

Valueless by exception

A variant can become "valueless by exception" if an exception is thrown during assignment or emplacement. You can check for this state with the valueless_by_exception() member function. A variant in this state can still be assigned to, but any other operation will throw std::bad_variant_access.

try {
  v.emplace<std::string>(invalid_string);
} catch (...) {
  if (v.valueless_by_exception()) {
    std::cout << "variant became valueless\n";
  }
}

Visitor exceptions

If an exception is thrown from a visitor function during a call to std::visit(), the exception will propagate out of the call to visit. Ensure your visitors handle exceptions appropriately.

try {
  std::visit(my_visitor, v);
} catch (const my_exception& e) {
  std::cerr << "Caught exception from visitor: "
    << e.what() << '\n';
}

Some general best practices:

  • Use std::variant only when the set of types is known at compile-time and is relatively small.
  • Prefer std::visit over directly accessing variant members. It's more type-safe and cleaner.
  • Handle std::bad_variant_access exceptions, either by preventing them with checks like std::holds_alternative, or catching them if they're expected.
  • Be aware of the "valueless by exception" state and handle it appropriately.
  • Ensure your visitor functions are exception-safe.

By following these practices, you can use std::variant safely and effectively in your C++ code.

Answers to questions are automatically generated and may not have been reviewed.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 125 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved