为什么我可以将带有by-value参数的函数绑定到采用左值引用的std :: function?

时间:2017-03-13 21:57:07

标签: c++ c++11

在挖掘找到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

2 个答案:

答案 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左值的内容来调用。然后它将调用基础函数f1f2。接收对int的引用的函数总是可以使用该引用来调用按值int的函数;提到的int将被复制。

通常std::function<R(T...)>可以存储带有任何签名的可调用对象,只要T...的函数调用运算符的std::function参数实际上可用于调用底层函数调用。签名不需要完全匹配。