C++对std::vector<std::variant>按类型过滤迭代的简化实现咨询
问题解答
问题1解答
可以实现,利用C++20引入的泛型lambda,不需要自定义任何结构体,也不需要编写冗余的类型转换或者全量指定模板参数,示例用法如下:
// 无需自定义任何结构体,直接在循环内写逻辑即可 for (const auto& green : colors | std::views::filter([](const auto& var) { return std::holds_alternative<Green>(var); }) | std::views::transform([](const auto& var) { return std::get<Green>(var); })) { std::cout << green.x << std::endl; }
如果想封装成可复用的管道适配器,也可以直接用lambda实现,不需要额外定义结构体:
template <typename T> inline constexpr auto variant_filter = std::views::filter([](const auto& var) { return std::holds_alternative<T>(var); }) | std::views::transform([](const auto& var) -> decltype(auto) { return std::get<T>(var); });
封装后可以直接按你原本的写法调用。
问题2解答
你的代码无法编译是两处细节不匹配导致的:
variant_get_t<T>::operator()的入参是非const左值引用,但你重载的operator|接收的输入范围是const R&类型,经过filter视图传递给transform的元素自带const属性,参数类型不匹配。- 两个仿函数的
operator()都没有加const修饰,C++标准库视图要求传入的可调用对象必须支持const调用,否则无法在视图内部执行调用逻辑。
修复后的代码片段
template <typename T> struct engaged_t { template <typename... Ts> // 加const修饰符 constexpr bool operator()(const std::variant<Ts...> &variant) const { return std::holds_alternative<T>(variant); } }; template <typename T> struct variant_get_t { template <typename... Ts> // 入参改为const引用,加const修饰符 constexpr decltype(auto) operator()(const std::variant<Ts...> &variant) const { return std::get<T>(variant); } };
修改后你注释掉的测试代码可以正常编译运行,输出结果为1和1。
内容的提问来源于stack exchange,提问作者NoSenseEtAl
相关产品推荐
相关产品推荐

