如何避免对同一变量重复使用std::forward?
避免重复使用std::forward的正确方法
你面临的问题很实际——重复写std::forward<T>(t)不仅冗余,还容易漏写导致调用错误的引用限定成员函数。直接用auto&&保存转发结果的方法是错误的,因为右值引用变量本身是左值,调用成员函数时会匹配左值限定版本,而非你需要的右值版本。
下面是两种可靠的解决方案:
方法一:用std::forward_as_tuple包装转发
利用std::forward_as_tuple创建一个包含转发引用的元组,每次通过std::get获取元素时,等价于直接调用std::forward<T>(t):
#include <tuple> template <typename T> void foo(T &&t) { auto forwarded = std::forward_as_tuple(t); std::get<0>(forwarded).foo(); std::get<0>(forwarded).bar(); std::get<0>(forwarded).baz(); }
原理:std::forward_as_tuple(t)会返回一个持有T&&类型元素的元组,每次调用std::get<0>(forwarded)时,返回的表达式值类别和std::forward<T>(t)完全一致——左值引用对应左值,右值引用对应右值,因此能正确匹配引用限定的成员函数。
方法二:用模板lambda封装转发逻辑(C++20及以上)
如果你的项目支持C++20,可以用模板lambda把转发逻辑封装起来,调用成员函数时只需传入成员指针:
#include <functional> // 用于std::invoke template <typename T> void foo(T &&t) { auto call_member = [&]<typename MemFunc>(MemFunc func) { std::invoke(func, std::forward<T>(t)); }; call_member(&std::remove_reference_t<T>::foo); call_member(&std::remove_reference_t<T>::bar); call_member(&std::remove_reference_t<T>::baz); }
这种方式更具可读性,尤其当成员函数数量较多时,只需关注成员函数名即可,无需重复处理转发逻辑。
内容的提问来源于stack exchange,提问作者geza
相关产品推荐
相关产品推荐

