I know what functors are and when to use them with stl algos. but didn't understand what did he mean in this topic:
我知道什么是函数,什么时候和stl algos一起用。但不明白他在这个话题上的意思:
c++ 11 faq
Can any one explain what std::bind
and std::function
are, when it should be used, some examples for newbie?
有谁能解释什么是std::bind和std:::function,当它应该被使用时,是一些新手的例子吗?
4 个解决方案
#1
149
std::bind
is for partial function application.
绑定用于部分功能应用。
That is, suppose you have a function object f
which takes 3 arguments:
假设有一个函数对象f有3个参数
f(a,b,c);
You want a new function object which only takes two arguments, defined as:
您需要一个新的函数对象,它只接受两个参数,定义为:
g(a,b) := f(a, 4, b);
g
is a "partial application" of the function f
: the middle argument has already been specified, and there are two left to go.
g是函数f的“部分应用”:已经指定了中间参数,还有两个参数要处理。
You can use std::bind
to get g
:
您可以使用std:绑定得到g:
auto g = bind(f, _1, 4, _2);
This is more concise than actually writing a functor class to do it.
这比实际编写一个函数类更简洁。
There are further examples in the article you link to. You generally use it when you need to pass a functor to some algorithm. You have a function or functor that almost does the job you want, but is more configurable (i.e. has more parameters) than the algorithm uses. So you bind arguments to some of the parameters, and leave the rest for the algorithm to fill in:
在你链接到的文章中还有更多的例子。当需要将一个函数传递给某个算法时,通常使用它。你有一个函数或函数函数,它几乎可以完成你想要的工作,但是它比算法使用的更具有可配置性(例如,有更多的参数)。因此,您将参数绑定到一些参数,剩下的部分留给算法来填充:
// raise every value in vec to the power of 7
std::transform(vec.begin(), vec.end(), some_output, std::bind(std::pow, _1, 7));
Here, pow
takes two parameters and can raise to any power, but all we care about is raising to the power of 7.
这里,pow有两个参数,可以取任意次幂,但我们关心的是取7次幂。
As an occasional use that isn't partial function application, bind
can also re-order the arguments to a function:
bind还可以将参数重新排序为一个函数:
auto memcpy_with_the_parameters_in_the_right_flipping_order = bind(memcpy, _2, _1, _3);
I don't recommend using it just because you don't like the API, but it has potential practical uses for example because:
我不建议仅仅因为你不喜欢API就使用它,但是它有潜在的实用价值,例如:
not2(bind(less<T>, _2, _1));
is a less-than-or-equal function (assuming a total order, blah blah). This example normally isn't necessary since there already is a std::less_equal
(it uses the <=
operator rather than <
, so if they aren't consistent then you might need this, and you might also need to visit the author of the class with a cluestick). It's the sort of transformation that comes up if you're using a functional style of programming, though.
是一个小于或等于的函数(假设总的顺序,等等)通常不需要这个示例,因为已经有一个std: less_equal(它使用<=操作符而不是<,因此如果它们不一致,那么您可能需要这个例子,您可能还需要用cluestick访问类的作者)。不过,如果你使用的是函数式编程,这种转换就会出现。
#2
8
std::bind was voted into library after proposal to include boost bind, primarily it is partial function specialization where-in you can fix few parameters and change others on fly. Now this is library way of doing lambdas in C++. As answered by Steve Jessop
绑定在提交了boost bind提议之后被投票到库中,主要是部分函数专门化,在这里您可以动态地修改一些参数并更改其他参数。这是用c++编写lambdas的库方法。Steve Jessop的回答
Now that C++11 supports lambda functions I don't feel any temptation to use std::bind anymore. I would rather use currying (partial specialization) with language feature than library feature.
既然c++ 11支持lambda函数,我就不会再忍不住使用std::bind了。我宁愿使用带有语言特性的局部专门化而不是库特性。
std::function objects are polymorphic functions. The basic idea is to be able to refer to all the callable objects interchangeably.
函数对象是多态函数。基本思想是能够交替引用所有可调用对象。
I would point you to these two links for further details:
我希望你能透过这两个连结了解更多详情:
Lambda functions in C++11: http://www.nullptr.me/2011/10/12/c11-lambda-having-fun-with-brackets/#.UJmXu8XA9Z8
Lambda函数在C++11中:http://www.nullptr.me/2011/10/12/c11- Lambda - fun_with_brackets/# .UJmXu8XA9Z8。
Callable entity in C++: http://www.nullptr.me/2011/05/31/callable-entity/#.UJmXuMXA9Z8
在c++中的可调用实体:http://www.nullptr.me/2011/05/31/callable-entity/#.UJmXuMXA9Z8
#3
5
I used it long time back to create a plugin thread pool in C++ ; Since the function was taking three parameters you can write like this
我用了很长时间,在c++中创建了一个插件线程池;因为函数有三个参数,你可以这样写
Suppose your method has the signature:
假设您的方法有以下签名:
int CTask::ThreeParameterTask(int par1, int par2, int par3)
To create a function object to bind the three parameters you can do like this
要创建一个函数对象来绑定三个参数,可以这样做
// a template class for converting a member function of the type int function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
public:
explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
:m_Ptr(_Pm) //okay here we store the member function pointer for later use
{}
//this operator call comes from the bind method
_Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
{
return ((_P->*m_Ptr)(arg1,arg2,arg3));
}
private:
_Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};
Now, in order to bind the parameters, we have to write a binder function. So, here it goes:
现在,为了绑定参数,我们需要编写一个绑定函数。所以,这里是:
template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
//This is the constructor that does the binding part
binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
:m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}
//and this is the function object
void operator()() const
{
m_fn(m_ptr,m1,m2,m3);//that calls the operator
}
private:
_Ptr m_ptr;
_Func m_fn;
_arg1 m1; _arg2 m2; _arg3 m3;
};
And, a helper function to use the binder3 class - bind3:
以及使用binder3类- bind3的辅助函数:
//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}
and here us how to call it
这是我们如何称呼它
F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3(
&CTask::ThreeParameterTask), task1,2122,23 );
Note: f3(); will call the method task1->ThreeParameterTask(21,22,23);
注意:f3();将调用方法task1->ThreeParameterTask(21、22、23);
For more gory details --> http://www.codeproject.com/Articles/26078/A-C-Plug-in-ThreadPool-Design
有关更多血腥的细节——> http://www.codeproject.com/articles/26078/a - c - plugin - threadpool - design
#4
4
One of the main use of std::function and std::bind is as safe function pointers. There is plenty of articles on web explaining how function pointers are useful in C/C++. For example, they are useful to implement callback mechanism. That is, you have some function that is going to take long time to execute but you don't want to wait for it to return then you can run that function on separate thread and give it a function pointer that it will callback after it completes.
std的主要用途之一::函数和std::bind是安全的函数指针。有很多关于web的文章解释了函数指针在C/ c++中是如何有用的。例如,它们对于实现回调机制非常有用。也就是说,你有一些函数需要很长时间才能执行但你不想等待它返回然后你可以在单独的线程上运行这个函数并给它一个函数指针它会在完成后回调。
Here's a sample code for how to use this:
下面是如何使用这个的示例代码:
class MyClass {
private:
//just shorthand to avoid long typing
typedef std::function<void (float result)> CallbackType;
//this function takes long time
void longRunningFunction(CallbackType callback)
{
//do some long running task
//...
//callback to return result
callback(result);
}
//this function gets called by longRunningFunction after its done
void afterCompleteCallback(float result)
{
std::cout << result;
}
public:
int longRunningFunctionAsync()
{
//create callback - this equivalent of safe function pointer
auto callback = std::bind(&MyClass::afterCompleteCallback,
this, std::placeholders::_1);
//normally you want to start below function on seprate thread,
//but for illustration we will just do simple call
longRunningFunction(callback);
}
};
#1
149
std::bind
is for partial function application.
绑定用于部分功能应用。
That is, suppose you have a function object f
which takes 3 arguments:
假设有一个函数对象f有3个参数
f(a,b,c);
You want a new function object which only takes two arguments, defined as:
您需要一个新的函数对象,它只接受两个参数,定义为:
g(a,b) := f(a, 4, b);
g
is a "partial application" of the function f
: the middle argument has already been specified, and there are two left to go.
g是函数f的“部分应用”:已经指定了中间参数,还有两个参数要处理。
You can use std::bind
to get g
:
您可以使用std:绑定得到g:
auto g = bind(f, _1, 4, _2);
This is more concise than actually writing a functor class to do it.
这比实际编写一个函数类更简洁。
There are further examples in the article you link to. You generally use it when you need to pass a functor to some algorithm. You have a function or functor that almost does the job you want, but is more configurable (i.e. has more parameters) than the algorithm uses. So you bind arguments to some of the parameters, and leave the rest for the algorithm to fill in:
在你链接到的文章中还有更多的例子。当需要将一个函数传递给某个算法时,通常使用它。你有一个函数或函数函数,它几乎可以完成你想要的工作,但是它比算法使用的更具有可配置性(例如,有更多的参数)。因此,您将参数绑定到一些参数,剩下的部分留给算法来填充:
// raise every value in vec to the power of 7
std::transform(vec.begin(), vec.end(), some_output, std::bind(std::pow, _1, 7));
Here, pow
takes two parameters and can raise to any power, but all we care about is raising to the power of 7.
这里,pow有两个参数,可以取任意次幂,但我们关心的是取7次幂。
As an occasional use that isn't partial function application, bind
can also re-order the arguments to a function:
bind还可以将参数重新排序为一个函数:
auto memcpy_with_the_parameters_in_the_right_flipping_order = bind(memcpy, _2, _1, _3);
I don't recommend using it just because you don't like the API, but it has potential practical uses for example because:
我不建议仅仅因为你不喜欢API就使用它,但是它有潜在的实用价值,例如:
not2(bind(less<T>, _2, _1));
is a less-than-or-equal function (assuming a total order, blah blah). This example normally isn't necessary since there already is a std::less_equal
(it uses the <=
operator rather than <
, so if they aren't consistent then you might need this, and you might also need to visit the author of the class with a cluestick). It's the sort of transformation that comes up if you're using a functional style of programming, though.
是一个小于或等于的函数(假设总的顺序,等等)通常不需要这个示例,因为已经有一个std: less_equal(它使用<=操作符而不是<,因此如果它们不一致,那么您可能需要这个例子,您可能还需要用cluestick访问类的作者)。不过,如果你使用的是函数式编程,这种转换就会出现。
#2
8
std::bind was voted into library after proposal to include boost bind, primarily it is partial function specialization where-in you can fix few parameters and change others on fly. Now this is library way of doing lambdas in C++. As answered by Steve Jessop
绑定在提交了boost bind提议之后被投票到库中,主要是部分函数专门化,在这里您可以动态地修改一些参数并更改其他参数。这是用c++编写lambdas的库方法。Steve Jessop的回答
Now that C++11 supports lambda functions I don't feel any temptation to use std::bind anymore. I would rather use currying (partial specialization) with language feature than library feature.
既然c++ 11支持lambda函数,我就不会再忍不住使用std::bind了。我宁愿使用带有语言特性的局部专门化而不是库特性。
std::function objects are polymorphic functions. The basic idea is to be able to refer to all the callable objects interchangeably.
函数对象是多态函数。基本思想是能够交替引用所有可调用对象。
I would point you to these two links for further details:
我希望你能透过这两个连结了解更多详情:
Lambda functions in C++11: http://www.nullptr.me/2011/10/12/c11-lambda-having-fun-with-brackets/#.UJmXu8XA9Z8
Lambda函数在C++11中:http://www.nullptr.me/2011/10/12/c11- Lambda - fun_with_brackets/# .UJmXu8XA9Z8。
Callable entity in C++: http://www.nullptr.me/2011/05/31/callable-entity/#.UJmXuMXA9Z8
在c++中的可调用实体:http://www.nullptr.me/2011/05/31/callable-entity/#.UJmXuMXA9Z8
#3
5
I used it long time back to create a plugin thread pool in C++ ; Since the function was taking three parameters you can write like this
我用了很长时间,在c++中创建了一个插件线程池;因为函数有三个参数,你可以这样写
Suppose your method has the signature:
假设您的方法有以下签名:
int CTask::ThreeParameterTask(int par1, int par2, int par3)
To create a function object to bind the three parameters you can do like this
要创建一个函数对象来绑定三个参数,可以这样做
// a template class for converting a member function of the type int function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
public:
explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
:m_Ptr(_Pm) //okay here we store the member function pointer for later use
{}
//this operator call comes from the bind method
_Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
{
return ((_P->*m_Ptr)(arg1,arg2,arg3));
}
private:
_Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};
Now, in order to bind the parameters, we have to write a binder function. So, here it goes:
现在,为了绑定参数,我们需要编写一个绑定函数。所以,这里是:
template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
//This is the constructor that does the binding part
binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
:m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}
//and this is the function object
void operator()() const
{
m_fn(m_ptr,m1,m2,m3);//that calls the operator
}
private:
_Ptr m_ptr;
_Func m_fn;
_arg1 m1; _arg2 m2; _arg3 m3;
};
And, a helper function to use the binder3 class - bind3:
以及使用binder3类- bind3的辅助函数:
//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}
and here us how to call it
这是我们如何称呼它
F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3(
&CTask::ThreeParameterTask), task1,2122,23 );
Note: f3(); will call the method task1->ThreeParameterTask(21,22,23);
注意:f3();将调用方法task1->ThreeParameterTask(21、22、23);
For more gory details --> http://www.codeproject.com/Articles/26078/A-C-Plug-in-ThreadPool-Design
有关更多血腥的细节——> http://www.codeproject.com/articles/26078/a - c - plugin - threadpool - design
#4
4
One of the main use of std::function and std::bind is as safe function pointers. There is plenty of articles on web explaining how function pointers are useful in C/C++. For example, they are useful to implement callback mechanism. That is, you have some function that is going to take long time to execute but you don't want to wait for it to return then you can run that function on separate thread and give it a function pointer that it will callback after it completes.
std的主要用途之一::函数和std::bind是安全的函数指针。有很多关于web的文章解释了函数指针在C/ c++中是如何有用的。例如,它们对于实现回调机制非常有用。也就是说,你有一些函数需要很长时间才能执行但你不想等待它返回然后你可以在单独的线程上运行这个函数并给它一个函数指针它会在完成后回调。
Here's a sample code for how to use this:
下面是如何使用这个的示例代码:
class MyClass {
private:
//just shorthand to avoid long typing
typedef std::function<void (float result)> CallbackType;
//this function takes long time
void longRunningFunction(CallbackType callback)
{
//do some long running task
//...
//callback to return result
callback(result);
}
//this function gets called by longRunningFunction after its done
void afterCompleteCallback(float result)
{
std::cout << result;
}
public:
int longRunningFunctionAsync()
{
//create callback - this equivalent of safe function pointer
auto callback = std::bind(&MyClass::afterCompleteCallback,
this, std::placeholders::_1);
//normally you want to start below function on seprate thread,
//but for illustration we will just do simple call
longRunningFunction(callback);
}
};