std::function 接受具有不同传递类型参数的 lambda 函数(通过 ref,通过 val)
std::function accepts lambda functions with arguments of different passing type (by ref, by val)
请看下面的代码
#include <iostream>
#include <functional>
#include <string>
int main()
{
std::function<void(std::string&)> theFunc;
std::string foo = "0";
theFunc = [](std::string a) { a = "1"; }; // this compiles but has a different function signature
theFunc(foo);
std::cout << "foo should be 1 but is " << foo << std::endl;
theFunc = [](auto a) { a = "2"; }; // this infers the wrong type for auto(by val not by ref), creates the wrong function signature and compiles
theFunc(foo);
std::cout << "foo should be 2 but is " << foo << std::endl;
theFunc = [](std::string& a) { a = "3"; }; // this compiles and correctly manipulates the string
theFunc(foo);
std::cout << "foo should be 3 and is " << foo << std::endl;
theFunc = [](auto& a) { a = "4"; }; // this compiles and correctly manipulates the string
theFunc(foo);
std::cout << "foo should be 4 and is " << foo << std::endl;
std::cin.get();
}
在代码示例中,我们 std::function 分配了不同类型的 lambda。
我理解的 lambda 3,因为函数签名匹配。
但是 lambda 1 创建了一个不同的函数签名,但编译正确。
Lambda 2 推断出错误的自动类型(通过 val 而不是通过 ref)并正确编译。
这是功能还是错误?我对函数 class / lambdas 和自动类型推断有什么误解?
更新:
感谢 Handy999 的回答,但为什么下面的代码无法编译?
std::function<void(std::string)> theFunc2;
theFunc2 = [](std::string& a) { a = "1"; }; // this doesn't compile and has a different function signature
theFunc2(foo);
与函数指针不同,std::function
获取所有可以按指定调用的内容。如有必要,它会创建一个小包装函数(在后台)。
在所有情况下代码
void smallWrapper(std::string& s) {
([](std::string a) { a = "1"; })(s);
}
void smallWrapper2(std::string& s) {
([](auto a) { a = "2"; })(s);
}
void smallWrapper3(std::string& s) {
([](std::string& a) { a = "3"; })(s);
}
void smallWrapper4(std::string& s) {
([](auto& a) { a = "4"; })(s);
}
可以调用。 auto
总是推导基类型,所以总是推导到 std::string
。因此,案例 2=案例 1,案例 4=案例 3。这就是 std::function
所做的和它应该做的。
第5种情况,果然如Caleth所说。你不能打电话
([](std::string& a) { a = "5"; })("string");
因为您不能将引用绑定到临时对象。 (在这里,包装函数会起作用。所以,它不是一个很好的模型。)对于 const 引用,它照常工作:
([](const std::string& a) { a = "6"; })("string");
请看下面的代码
#include <iostream>
#include <functional>
#include <string>
int main()
{
std::function<void(std::string&)> theFunc;
std::string foo = "0";
theFunc = [](std::string a) { a = "1"; }; // this compiles but has a different function signature
theFunc(foo);
std::cout << "foo should be 1 but is " << foo << std::endl;
theFunc = [](auto a) { a = "2"; }; // this infers the wrong type for auto(by val not by ref), creates the wrong function signature and compiles
theFunc(foo);
std::cout << "foo should be 2 but is " << foo << std::endl;
theFunc = [](std::string& a) { a = "3"; }; // this compiles and correctly manipulates the string
theFunc(foo);
std::cout << "foo should be 3 and is " << foo << std::endl;
theFunc = [](auto& a) { a = "4"; }; // this compiles and correctly manipulates the string
theFunc(foo);
std::cout << "foo should be 4 and is " << foo << std::endl;
std::cin.get();
}
在代码示例中,我们 std::function 分配了不同类型的 lambda。
我理解的 lambda 3,因为函数签名匹配。
但是 lambda 1 创建了一个不同的函数签名,但编译正确。
Lambda 2 推断出错误的自动类型(通过 val 而不是通过 ref)并正确编译。
这是功能还是错误?我对函数 class / lambdas 和自动类型推断有什么误解?
更新:
感谢 Handy999 的回答,但为什么下面的代码无法编译?
std::function<void(std::string)> theFunc2;
theFunc2 = [](std::string& a) { a = "1"; }; // this doesn't compile and has a different function signature
theFunc2(foo);
与函数指针不同,std::function
获取所有可以按指定调用的内容。如有必要,它会创建一个小包装函数(在后台)。
在所有情况下代码
void smallWrapper(std::string& s) {
([](std::string a) { a = "1"; })(s);
}
void smallWrapper2(std::string& s) {
([](auto a) { a = "2"; })(s);
}
void smallWrapper3(std::string& s) {
([](std::string& a) { a = "3"; })(s);
}
void smallWrapper4(std::string& s) {
([](auto& a) { a = "4"; })(s);
}
可以调用。 auto
总是推导基类型,所以总是推导到 std::string
。因此,案例 2=案例 1,案例 4=案例 3。这就是 std::function
所做的和它应该做的。
第5种情况,果然如Caleth所说。你不能打电话
([](std::string& a) { a = "5"; })("string");
因为您不能将引用绑定到临时对象。 (在这里,包装函数会起作用。所以,它不是一个很好的模型。)对于 const 引用,它照常工作:
([](const std::string& a) { a = "6"; })("string");