std::bind

std::bind

std::bind是一个标准的函数对象,它就像一个功能适配器,接受一个函数作为输入,并返回一个新函数对象作为输出。另外还附带若干个传递进函数的参数。

假设存在这样一个函数:

1
2
3
4
int add(int first, int second)
{
return first + second;
}

bind函数的第一个参数就是函数指针,后面的参数则是该函数的参数:

1
auto add_func = std::bind(&add, _1, _2);

这里add_func是一个函数对象,我们可以这样调用:

1
add_func(4,5);

它将在内部调用add()函数,并在_1的位置传递第一个参数,在_2的位置传递第二个参数。

现在假设我们想在一个特殊场景中使用这个add函数,我们应该将第一个参数始终固定为12,并让第二个参数由用户传递,即:

1
2
3
4
auto new_add_func = std::bind(&add, 12, _1);

int x = new_add_func(5);
// Will return 17

我们也可以使用std :: bind()重新排列参数,即_1和_2等决定要传递的参数的位:

1
2
3
auto mod_add_func = std::bind(&add, _2, _1);

// mod_add_func(12,15) === add(15, 12).

Use of std::bind in STL algorithms

由于std :: bind充当功能适配器并提供新的函数对象,因此它对于许多STL算法非常有用。

例如, 我们有一个数字列表,我们想要计算5的倍数。要实现这一点,我们有一个现有的函数,即:

1
2
3
4
5
6
7
bool divisible(int num , int den)
{
if(num % den == 0)
return true;
return false;

}

一般的算法是遍历判断,但我们可以使用std :: count_if这一个STL算法,即:

count_if (InputIterator firstValue, InputIterator lastValue, UnaryPredicate predFunctionObject);

通过bind函数,我们就可以将divisible转换为一元参数:

1
2
3
4
5
6
int approach_2()
{
int arr[10] = {1,20,13,4,5,6,10,28,19,15};
return std::count_if(arr, arr + sizeof(arr)/sizeof(int) , std::bind(&divisible, _1, 5));

}

What std::bind returns ?

除了auto,我们也可以使用std:;function Function对象存储它们,即

1
std::function<int (int) > mod_add_funcObj = std::bind(&add, 20, _1);