C++ Basics: Handle Alternative Value Types with std::visit
A value can be a count or a message without using an untyped pointer. std::variant records the active alternative, and std::visit dispatches to a callable that accepts it.
Prepare a scratch directory
Tested on Linux x86_64 with GCC 14.2.0. Install G++ and its C++ standard-library development files, and make g++ available on PATH. You also need Bash, a text editor, and mktemp, rm, and rmdir. No third-party C++ library is required.
Keep the same terminal open. Stop if setup fails, before saving the source:
start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1Run the example
Save this as variant-typed-visitation-demo.cpp:
#include <iostream>
#include <string>
#include <variant>
struct DisplayValue {
void operator()(int count) const
{
std::cout << "Count: " << count << '\n';
}
void operator()(const std::string& message) const
{
std::cout << "Message: " << message << '\n';
}
};
int main()
{
std::variant<int, std::string> result = 7;
std::visit(DisplayValue{}, result);
result = std::string{"waiting"};
std::visit(DisplayValue{}, result);
}Compile and run it. The second command runs only after compilation succeeds:
g++ -std=c++20 -Wall -Wextra -Werror -pedantic variant-typed-visitation-demo.cpp -o variant-typed-visitation-demo &&
./variant-typed-visitation-demoObserved output:
Count: 7
Message: waitingRead the result
The first visit selects the integer overload. After assigning a string, the second visit selects the string overload. The visitor receives the active value directly; no manual index-to-type mapping is needed. Both overloads return void, giving visitation a consistent result type.
Apply it carefully
The visitor must be valid for every alternative. With several variants, it must cover every relevant combination. Avoid an overly broad fallback overload if you want newly added types to trigger a compile-time review. A variant can become valueless after certain throwing operations; visiting that state throws std::bad_variant_access. This small example does not exercise exception recovery.
The C++ working draft specifies the relevant library behavior. The example uses interfaces available in C++20; the current working draft also describes later additions.
Clean up
Remove only the source and executable created here, then return to the starting directory:
rm -- variant-typed-visitation-demo.cpp variant-typed-visitation-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directoryIf the directory is not empty, inspect the remaining contents before removing anything else.
Acknowledgements
This post was created with assistance from AI.