Petty C++ - std::variant

std::variant 是 C++17 标准引入的一种 union，std::variant 可以在一个变量中存储不同类型的数据，并保持类型安全，这是传统的 union 所不能提供的。

主要特点

类型安全

使用 std::variant 可以保证任何时候都能确保访问正确的类型值，如果访问错误的类型会抛出 std::bad_variant_access 异常。

自动管理

std::variant 和 std::any 可以管理内部数据的创建和销毁，保证正确的资源管理。

访问控制

可以通过 std::get 访问 std::variant 中的数据（需要确保类型正确）

可以和 visit 结合使用

可以使用 std::visit 对存储在 std::variant 中的数据进行操作。

示例

Copy
#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; // 输出 20

v = 3.14f;
std::cout << std::get<float>(v) << std::endl; // 输出 3.14

v = "Hello, world";
std::cout << std::get<std::string>(v) << std::endl; // 输出 Hello, world

// 安全访问
try {
std::cout << std::get<float>(v) << std::endl; // 尝试获取float，但当前是std::string，将抛出异常
} catch (const std::bad_variant_access& e) {
std::cout << e.what() << std::endl; // 输出异常信息
}

// 使用 visit
std::visit([](auto&& arg) {
std::cout << arg << std::endl;
}, v); // 安全地打印当前存储的值，这里是 "Hello, world"

return 0;
}

在这个示例中，std::variant 被用来存储一个 int，一个 float，和一个 std::string。可以看到如何安全地使用 std::get 来访问 std::variant 中的数据，并且如何使用 std::visit 来应用函数或者访问者到存储的值上。

实际环境

Copy
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);
}

这段代码展示了如何使用 std::variant 和 std::visit 来处理不同类型的资源。这里，ResourceManager::flipResource 方法接受一个名为 resource 的 ResourceVariant 类型的参数，并返回一个同样类型的 ResourceVariant。这个 ResourceVariant 是一个 std::variant 类型，可以包含不同的资源类型（比如 IMAGE 或 Atlas）