为何无法使用右值参数按此方式绑定函数?
问题分析:前两个
do_task调用编译失败,第三个正常的原因 先看格式化后的代码:
#include <functional> #include <iostream> #include <string> #include <utility> using namespace std; template<typename Func, typename... Args> void do_task(Func &func, Args &&...args) { auto f = bind(func, forward<Args>(args)...); f(); } int main() { string name = "hello"; auto test_func = [](string name, string &&arg1, string &&arg2) -> void { cout << name << " " << arg1 << " " << arg2 << endl; }; // do_task(test_func,"test_one", "hello", string("world")); // 编译错误 // do_task(test_func, "test_tww", std::move(name), "world"); // 编译错误 do_task(test_func, "test_three", "hello", "world"); // 编译正常 return 0; }
核心原因拆解为两点:
- 右值引用的绑定规则:
string&&类型的参数只能接收右值,无法绑定到左值。 std::bind的参数处理逻辑:- 当给
bind传递string类型的右值(比如string("world")、std::move(name))时,bind会把这个右值复制一份,存储为自身内部的左值对象。调用f()时,bind会把这个存储的左值传给test_func的string&&参数——左值匹配不了右值引用,直接触发编译错误。 - 第三个调用里的
"hello"、"world"是字符串字面量,类型为const char*而非string。bind存储的是const char*的副本,调用f()时,该const char*会触发string的隐式构造,生成临时的string右值,刚好能匹配string&&参数,因此编译正常。
- 当给
如果想让前两个调用也正常运行,可以把test_func的参数改为const string&(兼容左值和右值),或者用std::forward_as_tuple配合std::apply替代bind,避免bind存储左值副本的问题。
内容的提问来源于stack exchange,提问作者Xuan Lin
相关产品推荐
相关产品推荐

