bind是这样一种机制,它可以将参数绑定于可调用对象,产生一个新的可调用实体,这种机制在函数回调时颇为有用
https://blog.youkuaiyun.com/caoshangpa/article/details/79173351
std::bind
参考资料
• cplusplus.com:http://www.cplusplus.com/reference/functional/bind/
• cppreference.com:http://en.cppreference.com/w/cpp/utility/functional/bind
std::bind简介
• 函数模板声明

// cplusplus.com
// simple(1)
template <class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
// with return type (2)
template <class Ret, class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
// GCC 4.8.2 - /usr/include/c++/4.8.2/tr1
template <typename _Functor, typename... _ArgTypes>
inline _Bind<typename _Maybe_wrap_member_pointer<_Functor>::type(_ArgTypes...)>
bind(_Functor __f, _ArgTypes... __args)
{
...
}
template <typename _Result, typename _Functor, typename... _ArgTypes>
inline _Bind_result<_Result, typename _Maybe_wrap_member_pointer<_Functor>::type (_ArgTypes...)>
bind(_Functor __f, _ArgTypes... __args)
{
...
}
// MS C++ 2013 \Microsoft Visual Studio 12.0\VC\include\functional
template <class _Fun, class... _Types>
inline _Bind<false, void, _Fun, _Types...>
bind(_Fun && _Fx, _Types &&... _Args)
{ // bind a function object
...
}
template <class _Rx, class... _Ftypes, class... _Types>
inline _Bind<true, _Rx, _Rx (* const)(_Ftypes...), _Types...>
bind(_Rx (*_Pfx)(_Ftypes...), _Types&&... _Args)
{ // bind a function pointer
...
}
template <class _Rx, class _Farg0, class... _Types>
inline _Bind<false, void, _Pmd_wrap<_Rx _Farg0::*, _Rx, _Farg0>, _Types...>
bind(_Rx _Farg0::* const _Pmd, _Types&&... _Args)
{ // bind a wrapped member object pointer
...
}
#define _IMPLICIT_PMF_WRAP(CALL_OPT, X1, CV_OPT) \
template <class _Rx, class _Farg0, class... _Ftypes, class... _Types> \
inline _Bind<true, _Rx, _Pmf_wrap<_Rx(CALL_OPT _Farg0::*)(_Ftypes...) CV_OPT, _Rx, _Farg0, _Ftypes...>, _Types...> \
bind(_Rx(CALL_OPT _Farg0::* const _Pmf)(_Ftypes...) CV_OPT, _Types&&... _Args) \
{ /* bind a wrapped CV_OPT member function pointer */ \
...
}
_MEMBER_CALL_CV(_IMPLICIT_PMF_WRAP, )
...

• 函数模板说明
以cplusplus.com中描述的原型说明:
基于Fn参数返回一个函数对象,并且以Args参数绑定为函数对象的参数。每个参数要么绑定一个参数值,要么绑定为一个std::placeholders。如果参数绑定成一个值,那么返回的函数对象将总使用绑定的参数值做为调用参数,即调用传入参数将不起作用;如果参数绑定为std::placeholders,那么返回的函数对象在被调用时需要传入实时参数,参数填充的位置即由placeholder指定的序号。
bind函数返回的函数对象类型和Fn一致,除非用户在Ret参数中指定了返回类型。需要注意的是,Ret参数只是一个模板参数,它并不能由传入该函数的参数进行隐式推导。
• 模板参数说明
以cplusplus.com中描述的原型说明:
Fn : 函数对象、普通函数指针或类成员函数指针。
Args : 用于绑定的参数列表。其中每个参数要么是参数值要么是一个placeholder
std::bind详解
• 绑定普通函数

#include <iostream>
#include <functional>
using namespace std;
int g_Minus(int i, int j)
{
return i - j;
}
int main()
{
function<int(int, int)> f1 = bind(g_Minus, 1, 2);
function<int()> f2 = bind(g_Minus, 1, 2); // 绑定参数返回的函数对象实际等同这种形式
function<int(int, int)> f3 = bind(g_Minus, placeholders::_1, placeholders::_2);
function<int(int)> f4 = bind(g_Minus, 1, placeholders::_1); // 绑定第一个参数
function<int(int)> f5 = bind(g_Minus, placeholders::_1, 1); // 绑定第二个参数
cout << f1(3, 2) << endl; // -1,实际传入参数将不起作用
cout << f2() << endl; // -1
cout << f3(3, 2) << endl; // 1
cout << f4(3) << endl; // -2
cout << f5(3) << endl; // 2
return 1;
}

• 绑定模板函数

#include <iostream>
#include <functional>
using namespace std;
template <class T>
T g_Minus(T i, T j)
{
return i - j;
}
int main()
{
function<int(int, int)> f1 = bind(g_Minus<int>, 1, 2);
function<int()> f2 = bind(g_Minus<int>, 1, 2); // 绑定参数返回的函数对象实际等同这种形式
function<int(int, int)> f3 = bind(g_Minus<int>, placeholders::_1, placeholders::_2);
function<int(int)> f4 = bind(g_Minus<int>, 1, placeholders::_1); // 绑定第一个参数
function<int(int)> f5 = bind(g_Minus<int>, placeholders::_1, 1); // 绑定第二个参数
cout << f1(3, 2) << endl; // -1,实际传入参数将不起作用
cout << f2() << endl; // -1
cout << f3(3, 2) << endl; // 1
cout << f4(3) << endl; // -2
cout << f5(3) << endl; // 2
return 1;
}

• 绑定lambda表达式

#include <iostream>
#include <functional>
using namespace std;
int main()
{
function<int(int, int)> f = bind([](int i, int j){ return i - j; }, placeholders::_1, placeholders::_2);
cout << f(2, 3) << endl; // -1
return 1;
}

• 绑定函数对象

#include <iostream>
#include <functional>
using namespace std;
struct Minus
{
int operator() (int i, int j)
{
return i - j;
}
};
int main()
{
function<int(int, int)> f = bind(Minus(), placeholders::_1, placeholders::_2);
cout << f(2, 3) << endl; // -1
return 1;
}

• 绑定类静态成员函数

#include <iostream>
#include <functional>
using namespace std;
class Math
{
public:
static int Minus(int i, int j)
{
return i - j;
}
};
int main()
{
function<int(int, int)> f = bind(&Math::Minus, placeholders::_1, placeholders::_2);
cout << f(2, 3) << endl; // -1
return 1;
}

• 绑定类对象成员函数

#include <iostream>
#include <functional>
using namespace std;
class Math
{
public:
int Minus(int i, int j)
{
return i - j;
}
};
int main()
{
Math m;
function<int(int, int)> f = bind(&Math::Minus, &m, placeholders::_1, placeholders::_2);
cout << f(2, 3) << endl; // -1
return 1;
}

• 返回值的类型转换

#include <iostream>
#include <functional>
using namespace std;
class Math
{
public:
int Minus(int i, int j)
{
return i - j;
}
};
struct Result
{
int m_Result;
Result() : m_Result(0) {}
Result(int result) : m_Result(result) {}
};
int main()
{
Math m;
auto f = bind<Result>(&Math::Minus, &m, placeholders::_1, placeholders::_2);
Result r = f(2, 3);
cout << r.m_Result << endl; // -1
return 1;
}
C++11新特性之七:bind和function
2018年01月26日 19:52:00 灿哥哥 阅读数:998
版权声明:本文为灿哥哥http://blog.youkuaiyun.com/caoshangpa原创文章,转载请标明出处。 https://blog.youkuaiyun.com/caoshangpa/article/details/79173351
一.std::bind
bind是这样一种机制,它可以将参数绑定于可调用对象,产生一个新的可调用实体,这种机制在函数回调时颇为有用。C++98中,有两个函数bind1st和bind2nd,它们分别用来绑定functor的第一个和第二个参数,都只能绑定一个参数。C++98提供的这些特性已经由于C++11的到来而过时,由于各种限制,我们经常使用bind而非bind1st和bind2nd。在C++11标准库中,它们均在functional头文件中。而C++STL很大一部分由Boost库扩充,STL中的shared_ptr等智能指针,bind及function都是由Boost库引入。在写代码过程中,要养成使用bind,function,lambda和智能指针的习惯,它们非常强大简洁实用。
1.过时的bind1st和bind2nd
bind1st(op, arg) :op(arg, param)
bind2nd(op, arg) :op(param, arg)
-
vector<int> coll {1, 2, 3, 4, 5, 11, 22, 5, 12}; -
// 查找第一个元素值大于10的元素 -
std::find_if(coll.begin(), coll.end(), // 范围 -
std::bind2nd(std::greater<int>(), 10));// 将10绑定到第二个参数,也就是 ......大于10 -
// 查找元素值大于10的元素的个数 -
int _count = count_if(coll.begin(), coll.end(), // 范围 -
std::bind1st(less<int>(), 10));// 将10绑定到第一个参数,也就是10小于......
2. C++11中的std::bind
-
//function object内部调用plus<>(也就是operator+),以占位符(placeholders)_1为第一个参数, -
//以10为第二个参数,占位符_1表示实际传入此表达式的第一实参,返回“实参+10”的结果值 -
auto plus10 = std::bind(std::plus<int> (), std::placeholders::_1, 10); -
std::cout << plus10(7) << std::endl;// 输出17
-
// (x + 10)*2,下面的代码中x=7 -
std::bind(std::multiplies<int>(), -
std::bind(std::plus<int>(), std::placeholders::_1, 10),// i+10 -
2)(7);
注意:上面所用的less<int>(),greater<int>()以及plus<int>()等都是C++预定义的Function Object。因此我们可以知道,bind可以把参数绑定到“函数对象”上。除此之外,bind()还可以把参数绑定到普通函数、类成员函数、甚至数据成员等。
3. 使用std::bind要注意的地方
(1)bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的。除非该参数被std::ref或者std::cref包装,才pass-by-reference。
(2)对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。placeholder是pass-by-reference的;
(3)bind的返回值是可调用实体,可以直接赋给std::function对象;
(4)对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的;
(5)类的this可以通过对象或者指针来绑定
4.一个例子
-
#include <iostream> -
#include <memory> -
#include <functional> -
void f(int n1, int n2, int n3, const int& n4, int n5) -
{ -
std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '\n'; -
} -
int g(int n1) -
{ -
return n1; -
} -
struct Foo { -
void print_sum(int n1, int n2) -
{ -
std::cout << n1+n2 << '\n'; -
} -
int data = 10; -
}; -
int main() -
{ -
using namespace std::placeholders; // for _1, _2, _3... -
// demonstrates argument reordering and pass-by-reference -
int n = 7; -
// (_1 and _2 are from std::placeholders, and represent future -
// arguments that will be passed to f1) -
auto f1 = std::bind(f, _2, _1, 42, std::cref(n), n); -
n = 10; -
f1(1, 2, 1001); // 1 is bound by _1, 2 is bound by _2, 1001 is unused -
// makes a call to f(2, 1, 42, n, 7) -
// nested bind subexpressions share the placeholders -
auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5); -
f2(10, 11, 12); // makes a call to f(12, g(12), 12, 4, 5); -
// bind to a pointer to member function -
Foo foo; -
auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1); -
f3(5); -
// bind to a pointer to data member -
auto f4 = std::bind(&Foo::data, _1); -
std::cout << f4(foo) << '\n'; -
}
输出结果;
-
2 1 42 10 7 -
12 12 12 4 5 -
100 -
10
二.std::function
类模版std::function是一种通用、多态的函数封装。std::function的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作,这些目标实体包括普通函数、Lambda表达式、bind表达式、函数指针以及其它函数对象,。std::function对象是对C++中现有的可调用实体的一种类型安全的包装(我们知道像函数指针这类可调用实体,是类型不安全的)。
最简单的理解就是:
通过std::function对C++中各种可调用实体(普通函数、Lambda表达式、函数指针、以及其它函数对象等)的封装,形成一个新的可调用的std::function对象;让我们不再纠结那么多的可调用实体。
-
#include <functional> -
#include <iostream> -
struct Foo { -
Foo(int num) : num_(num) {} -
void print_add(int i) const { std::cout << num_+i << '\n'; } -
int num_; -
}; -
void print_num(int i) -
{ -
std::cout << i << '\n'; -
} -
struct PrintNum { -
void operator()(int i) const -
{ -
std::cout << i << '\n'; -
} -
}; -
int main() -
{ -
// store a free function -
std::function<void(int)> f_display = print_num; -
f_display(-9); -
// store a lambda -
std::function<void()> f_display_42 = []() { print_num(42); }; -
f_display_42(); -
// store the result of a call to std::bind -
std::function<void()> f_display_31337 = std::bind(print_num, 31337); -
f_display_31337(); -
// store a call to a member function -
std::function<void(const Foo&, int)> f_add_display = &Foo::print_add; -
const Foo foo(314159); -
f_add_display(foo, 1); -
f_add_display(314159, 1); -
// store a call to a data member accessor -
std::function<int(Foo const&)> f_num = &Foo::num_; -
std::cout << "num_: " << f_num(foo) << '\n'; -
// store a call to a member function and object -
using std::placeholders::_1; -
std::function<void(int)> f_add_display2 = std::bind( &Foo::print_add, foo, _1 ); -
f_add_display2(2); -
// store a call to a member function and object ptr -
std::function<void(int)> f_add_display3 = std::bind( &Foo::print_add, &foo, _1 ); -
f_add_display3(3); -
// store a call to a function object -
std::function<void(int)> f_display_obj = PrintNum(); -
f_display_obj(18); -
}
输出结果:
-
-9 -
42 -
31337 -
314160 -
314160 -
num_: 314159 -
314161 -
314162 -
18
参考链接:http://en.cppreference.com/w/cpp/utility/functional/function
本文详细介绍了C++11中std::bind和std::function的功能和使用方法,包括如何绑定参数到可调用对象,产生新的可调用实体,以及std::function如何封装各种可调用实体。
1万+

被折叠的 条评论
为什么被折叠?



