2005年4月6日

函数bind1st 和 bind2nd 的说明

函数bind1st 和 bind2nd 都可以用于将二元算子(binary functor, bf)转换为一元算子(unary functor, uf)。转换过程需要二个参数:bf与值(v)。

值(v)是固定参数。换句话说,uf(x)等价于:
 * bf( x, v) - 用于bind2nd函数
 * bf( v, x) - 用于bind1st函数

在处理判别问题时使用bind1st 和bind2nd 函数是很有用的。这二个函数可将二元判别条件转换为一元判别条件。在将某一范围内(如容器中)的各个值与一基准值相比较时尤其有用。例如:

std::vector< int> a;
// . . . 给a赋值

// 下面的指令将删除所有小于30的元素
a.erase( std::remove_if( a.begin(), a.end(),
std::bind2nd( std::less< int>(), 30)), a.end());

在大多情况下,使用bind2nd就足够了,如上例所示。

但在类属编程时,要用函数来处理判别问题。通常要指定判别方向,并都用小于号"<" (std::less< type>)来表示。记住,要分别建立小于号"<"的各个重载算子"<=", ">=", 和 ">"。在这种情况下,就能看到bind1st 和bind2nd函数都很有用了。举例如下:

#include
#include
#include

template< class iterator, class predicate, class doer>
void for_each_if( iterator itFirst, iterator itLast, predicate pred, doer do_it)
{
while ( itFirst != itLast)
{
if ( pred( *itFirst)) do_it( *itFirst);
++itFirst;
}
}

void print( int i) { std::cout << i << " "; }

int main(int argc, char* argv[])
{
int aNumbers[] = { 10, 5, 89, 9, 30, -2, -8, 7, 33, 25, 30, 76, 0, 2};
int nCount = sizeof( aNumbers) / sizeof( aNumbers[ 0]);

// a < b
std::cout << "\nNumbers less than 30: ";
for_each_if( aNumbers, aNumbers + nCount,
std::bind2nd( std::less< int>(), 30), print);

std::cout << "\nNumbers bigger than 30: ";
// a > b
for_each_if( aNumbers, aNumbers + nCount,
std::bind1st( std::less< int>(), 30), print);

std::cout << "\nNumbers less or equal than 30: ";
// a <= b <=> !(a > b)
for_each_if( aNumbers, aNumbers + nCount,
std::not1( std::bind1st( std::less< int>(), 30)), print);

std::cout << "\nNumbers bigger or equal than 30: ";
// a >= b <=> !(a < b)
for_each_if( aNumbers, aNumbers + nCount,
std::not1( std::bind2nd( std::less< int>(), 30)), print);

return 0;
}

下面是一个类属函数示例,将删除所有小等于最小值或大等于最大值的元素:

// 删除所有满足'x <= least' 或 'x >= biggest'条件的元素
template< class iterator, class value_type, class predicate>
iterator remove_least_and_biggest(
iterator itFirst, iterator itLast,
value_type least, value_type biggest, predicate pred)
{
// 删除所有x <= least的元素
iterator itAfterRemovingLeast =
std::remove_if( itFirst, itLast,
std::not1( std::bind1st( pred, least)));
// 删除所有x >= biggest的元素
iterator itNewLast =
std::remove_if( itFirst, itAfterRemovingLeast,
std::not1( std::bind2nd( pred, biggest)));
return itNewLast;
}

如果进行忽略大小写字母的字符串比较,可用以下代码:

bool case_insensitive( const std::string & first, const std::string & second)
{ /* 代码 */ }

std::string aStrs[] = { "john", "John Doe", "Mircea", "nicole", "Nicole
Kidman", "Abraham", "Zeek" };
int n = sizeof( aStrs) / sizeof( aStrs[ 0]);
std::vector< std::string> a( aStrs, aStrs + n);
std::copy( a.begin(), a.end(),
std::ostream_iterator< std::string>( std::cout, ", "));
std::cout << std::endl;
// 删除不是"John Doe", "Mircea", "nicole"的所有元素
a.erase( remove_least_and_biggest(
a.begin(), a.end(), "John", "nicole kidman",
std::ptr_fun(case_insensitive)), a.end());
std::copy( a.begin(), a.end(),
std::ostream_iterator< std::string>( std::cout, ", "));


没有评论: