如何在C++模板类中仅对指定参数使用std::move转发
问题:仅对模板类中的右值引用参数执行std::move转发
你尝试将右值引用从模板类Foo转发到Bar,但遇到了一个问题:在Foo::do_something中,直接使用std::move(things)...会同时移动左值引用参数,而你只想对右值引用类型的参数执行move操作。你的代码如下:
#include <iostream> #include <string> #include <type_traits> #include <utility> template <typename... Ts> struct Bar { void do_something(Ts... things) { std::cout << "Got " << sizeof...(Ts) << " things" << std::endl; } }; template <typename... Ts> struct Foo { void do_something(Ts... things) { m_bar.do_something(things...); } Bar<Ts...> m_bar; }; int main(int argc, char** argv) { Foo<std::string&, std::string&&> foo; std::string hello1("Hello"); std::string hello2("Howdy"); foo.do_something(hello1, std::move(hello2)); return 0; }
解决方案:使用std::forward进行完美转发
最简洁且通用的解决方法是使用std::forward,它会根据模板参数的原始类型自动决定是保持左值引用还是转发为右值引用,完美匹配你的需求。
修改Foo::do_something的实现:
template <typename... Ts> struct Foo { void do_something(Ts... things) { // 用std::forward<Ts>对每个参数进行完美转发 m_bar.do_something(std::forward<Ts>(things)...); } Bar<Ts...> m_bar; };
原理说明
- 对于
Ts中的左值引用类型(比如std::string&),std::forward<Ts>(things)会将参数以左值的形式传递,不会触发move,保证原始左值的安全性。 - 对于
Ts中的右值引用类型(比如std::string&&),std::forward<Ts>(things)会将参数转换为右值,等价于执行std::move(things),满足转发右值的需求。
这种方式不需要手动区分哪个参数是左值还是右值,完全依赖模板参数的类型自动处理,是C++中处理转发场景的标准做法。
内容的提问来源于stack exchange,提问作者Jason Fernandez
相关产品推荐
相关产品推荐

