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

如何基于运行时索引向std::variant中emplace void*指针并适配现有模板?

关于std::variant运行时索引emplace的问题解答

问题1:是否可以通过运行时生成的索引,将某个void*指针emplace到std::variant中?

可以实现,但需注意两个核心限制:

  • std::variant::emplace的模板参数(目标类型的索引或类型)必须是编译期常量,因此不能直接将运行时索引传入模板参数,必须借助编译期生成的分支列表来匹配运行时索引。
  • 必须确保void*指针指向的对象类型与variant目标索引对应的类型完全一致,否则转换和构造会触发未定义行为。

问题2:修改模板以支持传入目标索引和待emplace的指针

原代码用于实现variant的循环切换,我们可以修改为根据指定运行时索引,将void*转换为对应类型并emplace到variant中。修改后的代码如下:

#include <variant>
#include <cstddef>

template <typename... Ts, std::size_t... Is>
void emplace_by_index(std::variant<Ts...>& v, std::size_t target_idx, void* ptr, std::index_sequence<Is...>)
{
    using Func = void (*)(std::variant<Ts...>&, void*);
    Func funcs[] = {
        +[](std::variant<Ts...>& var, void* p) {
            using TargetType = std::remove_reference_t<Ts>;
            var.template emplace<Is>(*static_cast<TargetType*>(p));
        }...
    };

    // 检查索引合法性,避免越界
    if (target_idx < sizeof...(Is)) {
        funcs[target_idx](v, ptr);
    }
}

template <typename... Ts>
void emplace_by_index(std::variant<Ts...>& v, std::size_t target_idx, void* ptr)
{
    emplace_by_index(v, target_idx, ptr, std::make_index_sequence<sizeof...(Ts)>());
}

代码说明:

  1. 函数数组生成:通过std::index_sequence生成与variant所有类型对应的函数数组,每个函数负责将void*转换为对应类型的指针,再调用emplace构造实例。
  2. 运行时索引匹配:根据传入的target_idx调用对应位置的函数,实现运行时索引到编译期emplace模板参数的映射。
  3. 合法性检查:添加索引越界检查,避免数组越界导致的未定义行为。

使用示例:

#include <iostream>
#include <string>

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

int main() {
    MyVariant var;
    std::string str = "test";
    emplace_by_index(var, 1, &str); // 索引1对应std::string类型
    std::cout << std::get<std::string>(var) << std::endl; // 输出"test"

    int num = 42;
    emplace_by_index(var, 0, &num); // 索引0对应int类型
    std::cout << std::get<int>(var) << std::endl; // 输出42

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 21:50:36