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

如何声明接受转发引用,按参数类型返回引用或副本的函数模板?

实现适配左值/右值的StringReplace函数模板

这需求挺实用的——要让一个函数模板根据传入字符串的左值/右值属性、是否const,自动生成对应的签名,对吧?我来给你写一个符合要求的实现:

完整模板代码

#include <string>
#include <type_traits>
#include <utility>

template<typename Str>
auto StringReplace(Str&& str, const std::string& from, const std::string& to)
    -> std::conditional_t<
        std::is_lvalue_reference_v<Str> && !std::is_const_v<std::remove_reference_t<Str>>,
        std::string&,
        std::string
    >
{
    // 分情况处理逻辑,用constexpr if在编译期分支
    if constexpr (std::is_lvalue_reference_v<Str> && !std::is_const_v<std::remove_reference_t<Str>>) {
        // 处理非const左值:直接修改原字符串,返回引用
        size_t pos = 0;
        while ((pos = str.find(from, pos)) != std::string::npos) {
            str.replace(pos, from.length(), to);
            pos += to.length();
        }
        return str;
    } else {
        // 处理const左值或右值:创建副本修改后返回,兼容RVO
        std::string temp(std::forward<Str>(str));
        size_t pos = 0;
        while ((pos = temp.find(from, pos)) != std::string::npos) {
            temp.replace(pos, from.length(), to);
            pos += to.length();
        }
        return temp; // RVO会自动优化,不需要std::move
    }
}

关键设计思路拆解

  • 万能引用与类型推导:Str&&是万能引用,会根据传入参数自动匹配类型:
    • 传入非const左值std::string&时,Str推导为std::string&,最终参数类型是std::string&(引用折叠规则:& && → &)
    • 传入const左值const std::string&时,Str推导为const std::string&,参数类型保持const std::string&
    • 传入右值std::string&&时,Str推导为std::string,参数类型是std::string&&
  • 编译期返回类型判断:用std::conditional_t做分支判断,只有当传入的是非const左值时返回引用,其他情况都返回值类型,完美匹配你要的签名
  • 高效分支处理:constexpr if在编译期就确定执行分支,非const左值直接修改原对象无拷贝;const左值走拷贝逻辑,右值走移动逻辑,最后返回临时对象时RVO会自动消除冗余拷贝

验证生成的签名

  • 传入非const左值:
    std::string s = "hello";
    StringReplace(s, "l", "x");
    
    生成签名:std::string& StringReplace(std::string&, const std::string&, const std::string&)
  • 传入const左值:
    const std::string s = "hello";
    auto result = StringReplace(s, "l", "x");
    
    生成签名:std::string StringReplace(const std::string&, const std::string&, const std::string&)
  • 传入右值:
    auto result = StringReplace(std::string("hello"), "l", "x");
    
    生成签名:std::string StringReplace(std::string&&, const std::string&, const std::string&),返回的副本会被RVO优化,无额外拷贝开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:20:51