如何在tuple包装类中正确使用std::get?
问题:Tuple包装类中std::get的正确使用方式
问题代码与现象
实现了一个存储tuple的类MultiStorer,代码如下:
#include <tuple> #include <iostream> using namespace std; template<typename... Types> class MultiStorer { public: tuple<Types...> my_tuple; MultiStorer(Types... elem) : my_tuple(tuple<Types...>(elem...)) {}; auto getElem(int&& pos) { return get<pos>(my_tuple); } };
调用时出现编译错误C2672: 'get': 找不到匹配的重载函数,但直接在类外通过std::get<0>访问成员my_tuple却能正常运行:
int main() { MultiStorer multistorer{ int(2),int(3) }; cout << get<0>(multistorer.my_tuple); // 正常运行 cout << multistorer.getElem(0); // 报错 return 0; }
错误原因
std::get的模板参数必须是编译期常量,而你定义的getElem函数接收的是运行时的int&& pos参数,这个参数的值在编译阶段无法确定,因此编译器无法实例化get<pos>这个模板函数,导致报错。
解决方案
把getElem改成模板函数,用非类型模板参数来指定tuple的索引位置,这样索引值就成了编译期常量,符合std::get的要求:
#include <tuple> #include <iostream> using namespace std; template<typename... Types> class MultiStorer { public: tuple<Types...> my_tuple; MultiStorer(Types... elem) : my_tuple(tuple<Types...>(elem...)) {}; // 改为模板函数,用非类型模板参数指定索引 template<std::size_t Pos> auto getElem() { return std::get<Pos>(my_tuple); } };
调用方式也需要调整为指定模板参数:
int main() { MultiStorer<int, int> multistorer{2, 3}; // 显式指定模板参数,避免推导歧义 cout << multistorer.getElem<0>(); // 正常运行 cout << multistorer.getElem<1>(); return 0; }
另外补充两点:
- 调用
MultiStorer时建议显式指定模板参数,避免编译器推导可能出现的问题; - 如果需要支持运行时动态索引的场景,不能直接用
std::get,可以考虑用std::apply结合访问者模式,或者手动编写类型分发逻辑,但这种方式会增加复杂度,且无法在编译期保证类型安全。
内容的提问来源于stack exchange,提问作者StefanOx26
相关产品推荐
相关产品推荐

