标准库中的 std::variant

std::variant 是 C++17 标准库中引入的一个类型安全的联合体(Union)。它允许一个对象在运行时存储多个不同类型中的一种,并且提供了安全访问和类型操作的功能。std::variant 是处理需要存储不同数据类型的场景时的理想选择,比传统的 unionvoid* 更安全、灵活。利用 std::get、std::get_if 和 std::visit,你可以有效地处理不同类型的数据,同时保持代码的清晰和安全。

基本概念

定义语法

#include <variant>

std::variant<Type1, Type2, ..., TypeN> my_variant;

主要特点

  • std::variant 提供类型安全的访问机制。使用 std::get 时,如果访问的类型与当前存储的类型不匹配,会抛出异常;使用 std::get_if 则会返回 nullptr,可以安全地检查当前存储的类型。
  • std::variant 可能带来一些性能开销,因为它需要在内部管理存储的类型和数据。对于性能敏感的应用,需要谨慎使用,确保性能开销在可接受范围内。
  • std::visit 提供了强大的功能来处理存储的不同类型。利用访客模式(Visitor Pattern)可以编写通用代码来处理 std::variant 中的各种类型。

基本用法

#include <iostream>
#include <variant>
#include <string>

// 定义一个 Variant 类型
using MyVariant = std::variant<int, double, std::string>;

int main() {
    MyVariant value;

    // 存储整数
    value = 42;
    std::cout << "Integer: " << std::get<int>(value) << std::endl;

    // 存储浮点数
    value = 3.14;
    std::cout << "Double: " << std::get<double>(value) << std::endl;

    // 存储字符串
    value = "Hello, World!";
    std::cout << "String: " << std::get<std::string>(value) << std::endl;

    // 使用 visitor 模式
    std::visit([](auto&& arg) {
        std::cout << "Visitor: " << arg << std::endl;
    }, value);

    return 0;
}

高级用法

  • 嵌套 std::variant, 可以在 std::variant 中嵌套其他 std::variant 或复杂的数据类型。这允许更复杂的数据结构的处理。
#include <iostream>
#include <variant>
#include <string>

using NestedVariant = std::variant<int, std::string>;
using ComplexVariant = std::variant<NestedVariant, double>;

int main() {
    ComplexVariant cv = NestedVariant("Nested variant");

    std::visit([](const auto& value) {
        std::visit([](const auto& inner) {
            std::cout << "Inner value: " << inner << std::endl;
        }, value);
    }, cv);

    return 0;
}

自定义实现

  • 在 C++ 中实现自定义的 Variant 类,可以利用 C++ 的模板和类型特性来创建一个简化版的 Variant 类。
#include <iostream>
#include <variant>
#include <string>
#include <stdexcept>

class Variant {
public:
    // 构造函数
    Variant() : data_(nullptr) {}
    Variant(int i) : data_(new int(i)) {}
    Variant(double d) : data_(new double(d)) {}
    Variant(const std::string& s) : data_(new std::string(s)) {}

    // 拷贝构造函数
    Variant(const Variant& other) {
        if (other.data_ == nullptr) {
            data_ = nullptr;
        } else if (auto pInt = dynamic_cast<int*>(other.data_)) {
            data_ = new int(*pInt);
        } else if (auto pDouble = dynamic_cast<double*>(other.data_)) {
            data_ = new double(*pDouble);
        } else if (auto pString = dynamic_cast<std::string*>(other.data_)) {
            data_ = new std::string(*pString);
        }
    }

    // 析构函数
    ~Variant() {
        delete data_;
    }

    // 获取存储的值
    template <typename T>
    T& get() {
        if (auto pValue = dynamic_cast<T*>(data_)) {
            return *pValue;
        }
        throw std::bad_cast();
    }

private:
    void* data_;
};

int main() {
    Variant value(42);

    try {
        int intValue = value.get<int>();
        std::cout << "Integer: " << intValue << std::endl;
    } catch (const std::bad_cast& e) {
        std::cerr << "Bad cast: " << e.what() << std::endl;
    }

    return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值