学习通用引用的时候,遇到一个奇怪的问题,定义的函数对象,不能被通用引用接收,但用auto自动推导的却可以。
#include <iostream>
#include <functional>
using namespace std;
template<typename Callback>
class Test{
public:
Test(Callback &&cb) {
}
};
int main() {
function<void(int)>func1 = [] (int a){ return a; };
auto func2 = [] (int a){ return a; };
auto test1 = Test<function<void(int)>>(func1); //报错
auto test2 = Test<function<void(int)>>(func2); //没问题
return 0;
}
报错结果提示:
error: cannot bind rvalue reference of type ‘std::function<void(int)>&&’ to lvalue of type ‘std::function<void(int)>’
意思是把func1当作了左值,但通用引用却没有特化出左值引用版本,而是只有右值引用版本,导致不能匹配。
把func1改成move(func1)后果然好了。
请问这个是为什么呢?而且func2就没问题,感觉很奇怪
你的代码有问题,类的构造函数参数要求的是一个右值引用,而你给的是一个左值,所以出错,改一下
#include <iostream>
#include <functional>
using namespace std;
template<typename Callback>
class Test {
public:
Test(Callback&& cb) {
}
};
int main() {
function<void(int)>func1 = [](int a) { return a; };
auto func2 = [](int a) { return a; };
auto test1 = Test<function<void(int)>>(std::move(func1)); //报错
auto test2 = Test<function<void(int)>>(func2); //没问题
return 0;
}
因为你的func1的返回值写的是void,但是{}中retuan a是返回的int类型,不匹配。
改成下面的就可以了:(只修改了func1那一行)
#include <iostream>
#include <functional>
using namespace std;
template<typename Callback>
class Test {
public:
Test(Callback&& cb) {
}
};
int main() {
function<int (int)>func1 = [](int a) { return a; }; // 修改 把void改成int就可以了
auto func2 = [](int a) { return a; };
auto test1 = Test<function<void(int)>>(func1); //报错
auto test2 = Test<function<void(int)>>(func2); //没问题
return 0;
}
还是自己搞明白了,这里的Callback&& cb被认为是右值引用,所以只能绑定右值,然后类型不匹配的时候反而对,是由于类型不匹配,编译器会默认添加static_cast<>,这样就产生了一个临时对象,这个临时对象是右值,所以就编译通过了