关于std::tuple实现中get函数类型兼容问题的技术问询
为什么
tuple<T, Ts...>能赋值给tuple<Ts...>&? 我在看一个简易std::tuple的实现时,对这段get函数的代码感到困惑:
template <size_t k, class... Ts> typename std::enable_if< k == 0, typename elem_type_holder<0, tuple<Ts...>>::type&>::type get(tuple<Ts...>& t) { return t.tail; } template <size_t k, class T, class... Ts> typename std::enable_if< k != 0, typename elem_type_holder<k, tuple<T, Ts...>>::type&>::type get(tuple<T, Ts...>& t) { //Why t could assign to different type? tuple<Ts...>& base = t; return get<k - 1>(base); }
我的疑问是:tuple<T, Ts...>与tuple<Ts...>是不同的类型,为什么这段代码能正常编译运行?
我自己好像找到了答案:是不是因为tuple<Ts...>是tuple<T,Ts...>的基类?
你猜的完全正确!这就是这段代码能正常工作的关键所在。
在这类简易tuple的实现中,普遍会采用递归继承的方式来构建tuple的结构:
tuple<T, Ts...>会直接继承自tuple<Ts...>- 最终所有变长tuple都会追溯到最底层的空tuple(比如
tuple<>)作为基类
举个直观的例子,tuple<int, std::string, double>的继承链是:tuple<int, std::string, double> → tuple<std::string, double> → tuple<double> → tuple<>
在C++的继承规则里,派生类的引用可以隐式转换为其基类的引用——就像你可以把Derived&赋值给Base&一样。所以这里的tuple<T, Ts...>&类型的t,能够直接赋值给tuple<Ts...>&类型的base,本质就是派生类到基类的引用转换。
这段get函数正是利用了这个继承特性,通过递归的方式逐步缩小tuple的“长度”:
- 当
k≠0时,把当前tuple引用转换为少一个元素的基类tuple引用 - 递归调用
get<k-1>,直到k=0时,直接返回当前tuple存储的元素(也就是t.tail)
这种递归继承是早期实现tuple的经典思路,虽然现在标准库的tuple实现会用到更高效的技巧(比如空基类优化、折叠表达式等),但核心都是通过拆解变长模板参数的结构来实现元素访问。
内容的提问来源于stack exchange,提问作者StereoMatching
相关产品推荐
相关产品推荐

