使用std::forward_as_tuple和std::tuple_cat转发参数遇值损坏问题
问题描述
我在编写从虚拟机栈取值的代码,已将虚拟机接口模拟为T get_one(int stack_pos)函数(需指定值类型和栈索引),目标是实现一个包装器,从栈中取出N个值并转发给C++函数。
我通过I_LOVE_RVALUES宏控制元组创建逻辑:定义该宏时使用std::forward_as_tuple,否则使用std::make_tuple。为追求低开销尝试右值转发,但出现值损坏问题;参考相关内容添加多处std::forward后问题仍未解决,改用传值版本可正常运行,但我想搞懂右值版本失效的原因。
我认为自己遵循了这些规则:
- 每个右值要么被使用,要么转发到另一个右值引用
- 元组仅传入
std::apply一次,后续不再复用,右值可被消耗
我猜测问题出在右值元组与std::tuple_cat的交互上,但无法明确具体原因。
现象说明
- 定义
I_LOVE_RVALUES时,第一行输出为垃圾值;未定义时输出应为012 - 第二行输出始终为
012
完整代码
#include <iostream> #include <string> #include <vector> #include <tuple> #include <cxxabi.h> #define I_LOVE_RVALUES #ifdef I_LOVE_RVALUES #define tuple_creator std::forward_as_tuple #else #define tuple_creator std::make_tuple #endif template<typename T> T get_one(int stack_pos) { // std::cout << typeid(T).name() + std::to_string(i) << std::endl; return static_cast<T>(stack_pos); } template<typename T> inline auto get_all(int i) { return tuple_creator(std::forward<T>(get_one<T>(i))); } // recursive case template<typename T0, typename T1, typename ...T> inline auto get_all(int i) { return std::tuple_cat( tuple_creator(std::forward<T0>(get_one<T0>(i))), get_all<T1, T...>(i+1) ); } void print_all(int i, float f1, float f2) { std::cout << i << f1 << f2 << std::endl; } int main() { auto&& tup = get_all<int, float, float>(0); std::string tup_typeid_name = typeid(decltype(tup)).name(); std::apply(print_all, tup); // here i'll make my forward_as_tuple directly std::apply(print_all, std::forward_as_tuple(std::move(0), std::move(1), std::move(2))); std::cout << tup_typeid_name << std::endl; }
内容的提问来源于stack exchange,提问作者saltyJeff
相关产品推荐
相关产品推荐

