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

如何对类模板参数使用std::forward 解决右值引用传参编译错误

错误原因

*转发引用(也叫万能引用)*和普通右值引用的适用场景有明确区别:

  • 仅当参数为函数自身模板参数的T&&类型时,才属于转发引用,会根据传入参数的值类型自动推导模板参数,触发引用折叠规则,可同时绑定左值和右值。你代码里的print函数符合这个要求,因此传左值data不会报错。
  • 类的成员函数add_to_list里的T是类模板的参数,在你实例化Data_List<std::vector<int>>时,T就已经固定为std::vector<int>,此时函数参数T&&就是普通的右值引用,只能绑定右值,你传入左值变量data自然会触发类型绑定错误。
正确实现方案

方案1:成员函数模板+转发引用

将add_to_list改为自带模板参数的成员函数,用函数自身的模板参数做转发,修改后的代码如下:

template<typename T>
class Data_List {
    std::vector<T> data_list;
    
public:
    Data_List() = default;
    ~Data_List() = default;
    
    std::size_t get_list_size() {
        return data_list.size();
    }
    
    // 修改为成员函数模板,使用自身的模板参数U做转发
    template<typename U>
    void add_to_list(U&& data) {
        std::cout << "before inside add_to_list: " << data.size() << std::endl;
        data_list.push_back(std::forward<U>(data));
        std::cout << "after inside add_to_list: " << data.size() << std::endl;
    }
};

修改后不管传入左值还是右值都可以正常编译运行,完美保留参数的值类型。

方案2:重载左值/右值版本

如果不想使用成员模板,也可以分别重载两个版本的add_to_list,分别处理左值和右值参数:

// 处理左值参数的版本
void add_to_list(const T& data) {
    std::cout << "before inside add_to_list: " << data.size() << std::endl;
    data_list.push_back(data);
    std::cout << "after inside add_to_list: " << data.size() << std::endl;
}

// 处理右值参数的版本
void add_to_list(T&& data) {
    std::cout << "before inside add_to_list: " << data.size() << std::endl;
    data_list.push_back(std::move(data));
    std::cout << "after inside add_to_list: " << data.size() << std::endl;
}

这种写法效果和完美转发一致,也可以同时支持左值和右值传入。

内容的提问来源于stack exchange,提问作者Harry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 06:06:05