跳转到内容

C++17 stdany

来自代码酷

std::any 是 C++17 标准引入的一个类型安全的容器,用于存储任意类型的单个值。它类似于动态类型语言中的变量,可以在运行时存储和检索不同类型的值,同时保持类型安全。与 void* 不同,std::any 会跟踪存储的类型信息,并在错误的类型访问时抛出异常。

基本介绍[编辑 | 编辑源代码]

std::any<any> 头文件中定义的类模板,它提供了一种灵活的方式来存储和操作不同类型的值。主要特点包括:

  • 类型安全:在访问存储的值时,会检查类型是否匹配。
  • 动态存储:可以存储任何可复制构造的类型(包括基本类型、类、指针等)。
  • 异常处理:如果尝试以错误的类型访问值,会抛出 std::bad_any_cast 异常。

基本用法[编辑 | 编辑源代码]

以下示例展示了 std::any 的基本操作:

#include <any>
#include <iostream>
#include <string>

int main() {
    std::any data;

    // 存储一个整数
    data = 42;
    std::cout << "Stored int: " << std::any_cast<int>(data) << '\n';

    // 存储一个字符串
    data = std::string("Hello, C++17!");
    std::cout << "Stored string: " << std::any_cast<std::string>(data) << '\n';

    // 检查是否有值
    if (data.has_value()) {
        std::cout << "Data has a value.\n";
    }

    // 尝试错误类型访问(抛出异常)
    try {
        std::cout << std::any_cast<double>(data) << '\n';
    } catch (const std::bad_any_cast& e) {
        std::cout << "Error: " << e.what() << '\n';
    }

    // 重置 any 对象
    data.reset();
    if (!data.has_value()) {
        std::cout << "Data is empty.\n";
    }
}

输出:

Stored int: 42
Stored string: Hello, C++17!
Data has a value.
Error: bad any_cast
Data is empty.

代码解释[编辑 | 编辑源代码]

1. std::any data 创建一个空的 any 对象。 2. data = 42 存储一个整数,std::any_cast<int>(data) 安全地提取该值。 3. data.has_value() 检查是否包含值。 4. std::any_cast<double>(data) 尝试以错误类型访问,抛出异常。 5. data.reset() 清空对象。

实际应用场景[编辑 | 编辑源代码]

std::any 在需要处理多种类型的场景中非常有用,例如:

  • 插件系统:存储不同插件的配置或状态。
  • 动态配置:解析 JSON 或 XML 时存储不确定类型的值。
  • 事件处理:传递不同类型的事件数据。

示例:动态配置存储[编辑 | 编辑源代码]

#include <any>
#include <vector>
#include <iostream>
#include <string>

struct Config {
    std::string name;
    std::any value;
};

int main() {
    std::vector<Config> settings = {
        {"timeout", 30},
        {"server", std::string("localhost")},
        {"debug", true}
    };

    for (const auto& cfg : settings) {
        std::cout << cfg.name << ": ";
        if (cfg.value.type() == typeid(int)) {
            std::cout << std::any_cast<int>(cfg.value);
        } else if (cfg.value.type() == typeid(std::string)) {
            std::cout << std::any_cast<std::string>(cfg.value);
        } else if (cfg.value.type() == typeid(bool)) {
            std::cout << std::boolalpha << std::any_cast<bool>(cfg.value);
        }
        std::cout << '\n';
    }
}

输出:

timeout: 30
server: localhost
debug: true

性能与注意事项[编辑 | 编辑源代码]

  • std::any 使用小对象优化(Small Object Optimization),小型对象(如基本类型)直接存储,大型对象(如类)在堆上分配。
  • 频繁的类型检查或错误访问可能影响性能。
  • 避免在性能关键路径中使用 std::any

类型检查与转换[编辑 | 编辑源代码]

可以通过 type() 成员函数获取存储值的类型信息:

std::any data = 3.14;
if (data.type() == typeid(double)) {
    std::cout << "Data is a double.\n";
}

std::variant 的比较[编辑 | 编辑源代码]

std::any std::variant
存储任意类型 存储预先定义的一组类型
运行时类型检查 编译时类型检查
可能抛出异常 通过 std::visit 安全访问

总结[编辑 | 编辑源代码]

std::any 提供了一种灵活且类型安全的方式来处理动态类型数据,适用于需要运行时类型不确定的场景。使用时需注意性能开销和异常处理。