std::variant is a union introduced in the C++17 standard. std::variant can store data of different types in a single variable while maintaining type safety, which traditional unions cannot provide.
Main Features#
Type Safety#
Using std::variant ensures that the correct type value is always accessed. If an incorrect type is accessed, it will throw a std::bad_variant_access exception.
Automatic Management#
std::variant and std::any can manage the creation and destruction of internal data, ensuring proper resource management.
Access Control#
Data in std::variant can be accessed through std::get (ensuring the correct type).
Can be used with visit#
std::visit can be used to operate on data stored in std::variant.
Example#
#include <variant>
#include <iostream>
#include <string>
int main() {
std::variant<int, float, std::string> v;
v = 20;
std::cout << std::get<int>(v) << std::endl; // Output: 20
v = 3.14f;
std::cout << std::get<float>(v) << std::endl; // Output: 3.14
v = "Hello, world";
std::cout << std::get<std::string>(v) << std::endl; // Output: Hello, world
// Safe access
try {
std::cout << std::get<float>(v) << std::endl; // Try to get float, but the current type is std::string, will throw an exception
} catch (const std::bad_variant_access& e) {
std::cout << e.what() << std::endl; // Output exception information
}
// Using visit
std::visit([](auto&& arg) {
std::cout << arg << std::endl;
}, v); // Safely print the current stored value, which is "Hello, world"
return 0;
}
In this example, std::variant is used to store an int, a float, and a std::string. It demonstrates how to safely use std::get to access data in std::variant and how to use std::visit to apply functions or visitors to the stored values.
Real Environment#
inline ResourceVariant ResourceManager::flipResource(ResourceVariant resource)
{
return std::visit([](auto&& res) -> ResourceVariant {
using T = std::decay_t<decltype(res)>;
if constexpr (std::is_same_v<T, IMAGE>) {
IMAGE flippedImg;
flipImage(&res, &flippedImg);
return flippedImg;
}
else if constexpr (std::is_same_v<T, Atlas>) {
Atlas flippedAtla;
flipAtlas(res, flippedAtla);
return flippedAtla;
}
}, resource);
}
This code shows how to use std::variant and std::visit to handle different types of resources. Here, the ResourceManager::flipResource method takes a ResourceVariant parameter named resource and returns a ResourceVariant of the same type. This ResourceVariant is a std::variant type that can contain different resource types (such as IMAGE or Atlas).