如何定义支持派生类的std::tuple指针类型get模板函数?
解决方案
要实现这个支持多态类型匹配的get模板函数,核心是在编译期从tuple的元素类型中,找到与目标类型U存在继承关系的基类指针类型。以下是具体实现:
1. 定义辅助类型Trait
首先编写一个模板元编程工具,用来遍历tuple的元素类型,筛选出符合条件的指针:
#include <tuple> #include <type_traits> // 递归查找第一个U可继承的基类指针类型 template <typename U, typename... Ts> struct find_base_ptr; // 递归终止:无匹配类型时触发编译错误 template <typename U> struct find_base_ptr<U> { static_assert(sizeof(U) == 0, "tuple中不存在匹配的基类指针类型"); }; // 匹配指针类型:检查U是否是T的派生类(含T本身) template <typename U, typename T, typename... Ts> struct find_base_ptr<U, T*> { using type = std::conditional_t< std::is_base_of_v<T, U>, T*, typename find_base_ptr<U, Ts...>::type >; }; // 跳过非指针类型(防护性偏特化) template <typename U, typename T, typename... Ts> struct find_base_ptr<U, T> : find_base_ptr<U, Ts...> {}; // 别名模板简化类型获取 template <typename U, typename Tuple> using find_base_ptr_t = typename find_base_ptr<U, typename Tuple::value_type...>::type;
2. 实现目标get函数
基于上面的Trait,编写最终的get模板:
template <typename U, typename... Ts> auto get(const std::tuple<Ts*...>& tuple) { using TargetPtr = find_base_ptr_t<U, std::tuple<Ts*...>>; return std::get<TargetPtr>(tuple); }
3. 代码说明
- 当调用
get<T>(tuple)时,std::is_base_of_v<T, T>返回true,直接匹配tuple中的T*类型,返回对应元素。 - 当调用
get<U>(tuple)(U继承自T)时,std::is_base_of_v<T, U>返回true,同样匹配到T*类型,返回对应元素。 - 如果tuple中存在多个符合条件的基类指针(比如U同时继承T1和T2,且tuple中包含T1和T2),会选择第一个匹配的类型。
- 无匹配类型时,编译期会触发
static_assert报错,避免运行时错误。
测试示例
struct T {}; struct U : T {}; int main() { std::tuple<T*, int*> tuple{new T{}, new int{42}}; // 通过基类T获取T* T* ptr_from_T = get<T>(tuple); // 通过派生类U获取T* T* ptr_from_U = get<U>(tuple); delete ptr_from_T; delete std::get<int*>(tuple); return 0; }
内容的提问来源于stack exchange,提问作者prestokeys
相关产品推荐
相关产品推荐

