在挖掘找到bug的来源之后,我惊讶地发现以下似乎是合法的C ++ 11(与GCC / clang与Wall编译很好)。特别是,为什么我可以指定f1
,它通过值将其参数赋予RefFunction
,该#include <iostream>
using namespace std;
void f1(int val) {
val = 1;
}
void f2(int& val) {
val = 2;
}
using RefFunction = std::function<void(int&)>;
int main()
{
using namespace std::placeholders;
int val = 42;
// I was expecting a compile error here telling me that f1 doesn't
// have the right signature (int instead of int&)
RefFunction f = f1;
f(val);
cout << val << endl; // prints 42
// This makes sense, f2 takes argument by reference
f = f2;
f(val);
cout << val << endl; // prints 2
return EXIT_SUCCESS;
}
期望通过引用参数?
我尝试使用谷歌搜索解释,但没有发现任何相关内容,可能是因为我不确切知道谷歌的用途。如果有人能指导我为什么这是合法的,我真的很感激。
-Message
答案 0 :(得分:5)
暂时搁置标准,请考虑以下几点:
void f1(int val) {
val = 1;
}
void f2(int& val) {
val = 2;
}
void WrapperFunction(int& val)
{
f1(val); // Should be OK
f2(val); // Should be OK.
}
编译器不应该对上面的代码有任何问题。如果您认为WrapperFunction
类似于std::function
,则无论std::function
是使用f1
还是f2
构建,编译器都不会有任何问题。< / p>
答案 1 :(得分:4)
std::function
的模板参数强制执行std::function
的方式;因此,RefFunction
只能使用类型为int
的左值或可以隐式转换为类型int
左值的内容来调用。然后它将调用基础函数f1
或f2
。接收对int
的引用的函数总是可以使用该引用来调用按值int
的函数;提到的int
将被复制。
通常std::function<R(T...)>
可以存储带有任何签名的可调用对象,只要T...
的函数调用运算符的std::function
参数实际上可用于调用底层函数调用。签名不需要完全匹配。