You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从std::any提取真实类型并创建对应类型的std::vector?

问题描述

我用std::map<TYPE, std::any>存储枚举TYPE到不同整数类型的映射,因为需要灵活存储多类型数据所以选了std::any。现在想根据key对应的std::any里的真实类型创建该类型的std::vector,但下面的代码编译报错,原因是decltype返回std::any&,没法当vector的模板参数。

示例代码

#include <iostream>
#include <any>
#include <vector>
#include <map>
#include <typeinfo>

typedef enum TYPE{
    INT8=0,
    INT16=1,
    INT32=2
} TYPE;

int main()
{
    std::map<TYPE, std::any> myMap;
    
    myMap[TYPE::INT8] = (int8_t)0;
    myMap[TYPE::INT16] = (int16_t)0;
    myMap[TYPE::INT32] = (int32_t)0;

    std::vector<decltype(myMap[TYPE::INT8])> vec; 
}

编译错误片段

/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/new_allocator.h:63:26: error: forming pointer to reference type 'std::any&'
   63 |       typedef _Tp*       pointer;

/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/new_allocator.h:112:7: error: forming pointer to reference type 'std::any&'
  112 |       allocate(size_type __n, const void* = static_cast<const void*>(0))

/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/stl_vector.h:1293:7: error: 'void std::vector<_Tp, _Alloc>::push_back(value_type&&) [with _Tp = std::any&; _Alloc = std::allocator<std::any&>; value_type = std::any&]' cannot be overloaded with 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::any&; _Alloc = std::allocator<std::any&>; value_type = std::any&]'
 1293 |       push_back(value_type&& __x)

请问怎么实现从std::any中提取真实类型并创建对应类型的std::vector?


解决方案

std::any的核心是类型擦除,编译期无法直接获取它存储的真实类型,必须通过运行时的类型匹配来处理。可以借助std::any_cast结合类型分发的方式实现需求,下面是两种可行的方案:

方案一:基于枚举类型映射确定存储类型

既然TYPE枚举和存储的整数类型是一一对应的,直接通过枚举值分支创建对应类型的vector即可,这种方式简单直接:

#include <iostream>
#include <any>
#include <vector>
#include <map>
#include <memory>

typedef enum TYPE{
    INT8=0,
    INT16=1,
    INT32=2
} TYPE;

int main()
{
    std::map<TYPE, std::any> myMap;
    myMap[TYPE::INT8] = (int8_t)0;
    myMap[TYPE::INT16] = (int16_t)0;
    myMap[TYPE::INT32] = (int32_t)0;

    // 用智能指针存储任意类型的vector
    std::unique_ptr<void> vec_ptr;

    TYPE target_key = TYPE::INT8;
    switch(target_key) {
        case TYPE::INT8:
            vec_ptr = std::make_unique<std::vector<int8_t>>();
            break;
        case TYPE::INT16:
            vec_ptr = std::make_unique<std::vector<int16_t>>();
            break;
        case TYPE::INT32:
            vec_ptr = std::make_unique<std::vector<int32_t>>();
            break;
        default:
            // 处理未知类型
            break;
    }

    // 如果需要操作vector,同样需要通过枚举分支做类型转换
    if(target_key == TYPE::INT8) {
        auto& vec = *static_cast<std::vector<int8_t>*>(vec_ptr.get());
        vec.push_back(12);
        std::cout << vec[0] << std::endl;
    }
}

方案二:利用std::any的类型信息动态创建vector

如果枚举和类型的对应关系不固定,或者需要从std::any直接推导类型,可以用std::type_index结合类型映射表,在运行时匹配类型并创建vector:

#include <iostream>
#include <any>
#include <vector>
#include <map>
#include <typeindex>
#include <functional>
#include <memory>

typedef enum TYPE{
    INT8=0,
    INT16=1,
    INT32=2
} TYPE;

int main()
{
    std::map<TYPE, std::any> myMap;
    myMap[TYPE::INT8] = (int8_t)0;
    myMap[TYPE::INT16] = (int16_t)0;
    myMap[TYPE::INT32] = (int32_t)0;

    // 构建类型到vector创建函数的映射
    std::map<std::type_index, std::function<std::unique_ptr<void>()>> vec_creators = {
        {typeid(int8_t), [](){ return std::make_unique<std::vector<int8_t>>(); }},
        {typeid(int16_t), [](){ return std::make_unique<std::vector<int16_t>>(); }},
        {typeid(int32_t), [](){ return std::make_unique<std::vector<int32_t>>(); }}
    };

    TYPE target_key = TYPE::INT16;
    auto& any_val = myMap[target_key];
    auto type_idx = std::type_index(any_val.type());

    // 查找对应的创建函数并生成vector
    auto it = vec_creators.find(type_idx);
    if(it != vec_creators.end()) {
        auto vec_ptr = it->second();
        // 操作vector时同样需要类型转换
        if(type_idx == typeid(int16_t)) {
            auto& vec = *static_cast<std::vector<int16_t>*>(vec_ptr.get());
            vec.push_back(256);
            std::cout << vec[0] << std::endl;
        }
    }
}

关键说明

  • std::any存储的类型信息只有运行时才能获取,所以无法在编译期直接生成对应类型的vector,必须通过运行时分支或类型映射来处理。
  • 因为vector的类型是运行时确定的,所以需要用void*或者智能指针来统一存储,操作时必须通过类型转换还原真实类型。
  • 如果业务场景中枚举和类型的对应是固定的,方案一更高效且代码更简洁;如果类型可能动态扩展,方案二更灵活。

内容的提问来源于stack exchange,提问作者ad99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 23:50:28