You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 20:02:48