为什么std::function可以隐式转换为参数更多的std::function?
Why does std::function can implicit convert to a std::function which has more parameter?
我有:
void print_str(std::shared_ptr<std::string> str) {
std::cout << str->c_str() << std::endl;
}
int main() {
auto str = std::make_shared<std::string>("Hello");
std::function<void()> f = std::bind(print_str, str);
f(); // correctly print: Hello
return 0;
}
我认为std::bind(print_str, str)
的类型是std::function<void(std::shared_ptr<std::string>)>
,但是上面的代码是正确的运行。 std::bind
有什么技巧吗?
环境:centos, gcc82
std::bind所做的是正确的。它使用您提供的值 (str) 来调用 print_str。所以你不需要再指定它并且总是被绑定值替换。
#include <iostream>
#include <functional>
int sum(int value1, int value2) {
return value1 + value2;
}
int main() {
std::function<int(int, int)> f1 = std::bind(sum, std::placeholders::_1, std::placeholders::_1);
std::function<int(int)> f2 = std::bind(sum, 10, std::placeholders::_1);
std::function<int()> f3 = std::bind(sum, 100, 200);
std::function<int(int)> f4 = std::bind(sum, std::placeholders::_1, 200);
int a = 1;
int b = 2;
std::cout << "the sum of " << a << " and " << b << " is: " << f1(a, b) << std::endl;
std::cout << "the sum of " << 10 << " and " << b << " is: " << f2(b) << std::endl;
std::cout << "the sum of " << 100 << " and " << 200 << " is: " << f3() << std::endl;
std::cout << "the sum of " << 200 << " and " << b << " is: " << f4(b) << std::endl;
return 0;
}
输出:
the sum of 1 and 2 is: 2
the sum of 10 and 2 is: 12
the sum of 100 and 200 is: 300
the sum of 200 and 2 is: 202
f1
不绑定任何值,但占位符和 returns 一个 int(int, int)
类函数
f2
绑定一个值和一个占位符,returns 一个 int(int)
类函数
f3
绑定两个值且没有占位符和 returns 一个 int()
类函数
f4
类似于 f2
,只是占位符现在是第一个参数而不是第二个参数。
您的代码属于 f3
情况。
I think the type of std::bind(print_str, str)
is std::function<void(std::shared_ptr<std::string>)>
不,std::bind(print_str, str)
的类型是未指定的函子类型,类似于
class binder
{
void(*f)(std::shared_ptr<std::string>);
std::shared_ptr<std::string> p;
public:
template<typename... Args>
void operator()(Args... ) { f(p); }
};
请注意,这可以使用任何参数或 none.
调用
您在这里遇到的是正确的,并且正是在做 std::bind
的设计目的。
简单来说:
它将采用 n
个参数的函数转换为采用 m
个参数的函数(其中 n >= m
)。
在您的特定情况下,您给它一个带一个参数的函数并取回一个带零参数的函数。这个新函数将在内部调用 print_str
并始终将 str
作为参数传递。
旁注:
因为 C++11 中有 lambda,所以 std::bind
有点多余。
你所做的与此完全相同:
void print_str(std::shared_ptr<std::string> str) {
std::cout << str->c_str() << std::endl;
}
int main() {
auto str = std::make_shared<std::string>("Hello");
std::function<void()> f = [=]() { print_str(str); };
f(); // correctly print: Hello
return 0;
}
希望这也有助于理解 std::bind
在幕后做了什么。
我有:
void print_str(std::shared_ptr<std::string> str) {
std::cout << str->c_str() << std::endl;
}
int main() {
auto str = std::make_shared<std::string>("Hello");
std::function<void()> f = std::bind(print_str, str);
f(); // correctly print: Hello
return 0;
}
我认为std::bind(print_str, str)
的类型是std::function<void(std::shared_ptr<std::string>)>
,但是上面的代码是正确的运行。 std::bind
有什么技巧吗?
环境:centos, gcc82
std::bind所做的是正确的。它使用您提供的值 (str) 来调用 print_str。所以你不需要再指定它并且总是被绑定值替换。
#include <iostream>
#include <functional>
int sum(int value1, int value2) {
return value1 + value2;
}
int main() {
std::function<int(int, int)> f1 = std::bind(sum, std::placeholders::_1, std::placeholders::_1);
std::function<int(int)> f2 = std::bind(sum, 10, std::placeholders::_1);
std::function<int()> f3 = std::bind(sum, 100, 200);
std::function<int(int)> f4 = std::bind(sum, std::placeholders::_1, 200);
int a = 1;
int b = 2;
std::cout << "the sum of " << a << " and " << b << " is: " << f1(a, b) << std::endl;
std::cout << "the sum of " << 10 << " and " << b << " is: " << f2(b) << std::endl;
std::cout << "the sum of " << 100 << " and " << 200 << " is: " << f3() << std::endl;
std::cout << "the sum of " << 200 << " and " << b << " is: " << f4(b) << std::endl;
return 0;
}
输出:
the sum of 1 and 2 is: 2
the sum of 10 and 2 is: 12
the sum of 100 and 200 is: 300
the sum of 200 and 2 is: 202
f1
不绑定任何值,但占位符和 returns 一个 int(int, int)
类函数
f2
绑定一个值和一个占位符,returns 一个 int(int)
类函数
f3
绑定两个值且没有占位符和 returns 一个 int()
类函数
f4
类似于 f2
,只是占位符现在是第一个参数而不是第二个参数。
您的代码属于 f3
情况。
I think the type of
std::bind(print_str, str)
isstd::function<void(std::shared_ptr<std::string>)>
不,std::bind(print_str, str)
的类型是未指定的函子类型,类似于
class binder
{
void(*f)(std::shared_ptr<std::string>);
std::shared_ptr<std::string> p;
public:
template<typename... Args>
void operator()(Args... ) { f(p); }
};
请注意,这可以使用任何参数或 none.
调用您在这里遇到的是正确的,并且正是在做 std::bind
的设计目的。
简单来说:
它将采用 n
个参数的函数转换为采用 m
个参数的函数(其中 n >= m
)。
在您的特定情况下,您给它一个带一个参数的函数并取回一个带零参数的函数。这个新函数将在内部调用 print_str
并始终将 str
作为参数传递。
旁注:
因为 C++11 中有 lambda,所以 std::bind
有点多余。
你所做的与此完全相同:
void print_str(std::shared_ptr<std::string> str) {
std::cout << str->c_str() << std::endl;
}
int main() {
auto str = std::make_shared<std::string>("Hello");
std::function<void()> f = [=]() { print_str(str); };
f(); // correctly print: Hello
return 0;
}
希望这也有助于理解 std::bind
在幕后做了什么。