如何声明接受转发引用,按参数类型返回引用或副本的函数模板?
实现适配左值/右值的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&&
- 传入非const左值
- 编译期返回类型判断:用
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
相关产品推荐
相关产品推荐

