如何基于运行时索引向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)>()); }
代码说明:
- 函数数组生成:通过
std::index_sequence生成与variant所有类型对应的函数数组,每个函数负责将void*转换为对应类型的指针,再调用emplace构造实例。 - 运行时索引匹配:根据传入的
target_idx调用对应位置的函数,实现运行时索引到编译期emplace模板参数的映射。 - 合法性检查:添加索引越界检查,避免数组越界导致的未定义行为。
使用示例:
#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
相关产品推荐
相关产品推荐

