如何从std::tuple类型生成含my_struct指针的std::variant
解决可变参数模板中展开tuple类型到std::variant的问题
要实现将must_be_params中tuple的类型参数包展开,为每个objects生成对应的my_struct<Object, Args...>*并组合成std::variant,可以通过模板元编程拆解tuple参数包并生成目标类型,具体实现如下:
1. 定义辅助模板工具
先实现三个辅助模板,分别用于组合目标指针类型、生成variant类型、拆解tuple的参数包:
#include <variant> #include <vector> #include <tuple> #include <type_traits> // 原定义保持不变 template<typename T, typename ...Args> struct my_struct; struct A { my_struct<A, int, int, char> _a_var; }; struct B { my_struct<B, int, int, char> _b_bar; }; template<typename ...Types> struct params { using tuple_params = std::tuple<Types...>; }; // 辅助1:将单个Object与Args参数包组合成my_struct<Object, Args...>* template<typename Object, typename... Args> using struct_ptr_t = my_struct<Object, Args...>*; // 辅助2:将Objects参数包和Args参数包组合成std::variant类型 template<typename... Objects, typename... Args> struct variant_type_helper { using type = std::variant<struct_ptr_t<Objects, Args...>...>; }; // 辅助3:拆解tuple类型,提取其内部的模板参数包 template<typename Tuple> struct tuple_unpacker; template<typename... Args> struct tuple_unpacker<std::tuple<Args...>> { // 为传入的Objects参数包生成对应的variant类型 template<typename... Objects> using variant_type = typename variant_type_helper<Objects..., Args...>::type; };
2. 修改my_problem结构体
在my_problem中利用辅助模板生成目标vector类型,并添加静态断言确保传入的my_struct参数包与must_be_params一致:
template<typename must_be_params, typename ...objects> struct my_problem{ // 从must_be_params中提取tuple参数,生成对应的std::variant类型 using variant_t = typename tuple_unpacker<typename must_be_params::tuple_params>::template variant_type<objects...>; using vector_t = std::vector<variant_t>; template<typename R, typename ...types> void some_random_method( my_struct<R, types...> *ptr) { // 静态断言:确保传入的my_struct参数包与must_be_params指定的类型一致 static_assert(std::is_same_v<std::tuple<types...>, typename must_be_params::tuple_params>, "my_struct的参数包必须与must_be_params指定的类型一致"); _vector.emplace_back(ptr); } private: vector_t _vector; }; // 测试实例化 void some_random_function() { A _a; B _b; my_problem<params<int, int, char>, A, B> _my; _my.some_random_method(&_a._a_var); _my.some_random_method(&_b._b_bar); }
效果说明
当实例化my_problem<params<int, int, char>, A, B>时:
variant_t会被推导为std::variant<my_struct<A, int, int, char>*, my_struct<B, int, int, char>*>_vector的类型就是std::vector<上述variant类型>,完全符合需求。
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

