`
dongtianzhe
  • 浏览: 21525 次
  • 性别: Icon_minigender_1
  • 来自: 长春
最近访客 更多访客>>
社区版块
存档分类
最新评论

Boost学习2-函数对象

阅读更多
所谓的函数对象是指那些可以被传入到其他函数或者从其他函数返回的那一类函数。

boost::bind:
在C++标准库中有两个绑定器:std::bind1st和std::bind2nd,他们可以指定给定函数对象的参数。看下面的例子:
#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <functional> 

class add 
  : public std::binary_function<int, int, void> 
{ 
public: 
  void operator()(int i, int j) const 
  { 
    std::cout << i + j << std::endl; 
  } 
}; 

int main() 
{ 
  std::vector<int> v; 
  v.push_back(1); 
  v.push_back(3); 
  v.push_back(2); 

  std::for_each(v.begin(), v.end(), std::bind1st(add(), 10)); 
} 


这里bind1st的意思是将函数对象add的第一个参数绑定为10,然后形成一个1元函数对象传递给for_each中,功能是将vector中所有元素都加10。

这个例子我们可以用boost::bind进行简化:
#include <boost/bind.hpp> 
#include <iostream> 
#include <vector> 
#include <algorithm> 

void add(int i, int j) 
{ 
  std::cout << i + j << std::endl; 
} 

int main() 
{ 
  std::vector<int> v; 
  v.push_back(1); 
  v.push_back(3); 
  v.push_back(2); 

  std::for_each(v.begin(), v.end(), boost::bind(add, 10, _1)); 
} 


其中_1为占位符,这个bind的意思是add第一个参数是10,第二个参数是占位符,在执行时容器中的元素通过占位符传入。

除了_1外,boost::bind还定义了_2和_3,通过这些占位符bind可以产生一元、二元和三元的函数。我们看一下二元函数的例子:
#include <boost/bind.hpp> 
#include <vector> 
#include <algorithm> 

bool compare(int i, int j) 
{ 
  return i > j; 
} 

int main() 
{ 
  std::vector<int> v; 
  v.push_back(1); 
  v.push_back(3); 
  v.push_back(2); 

  std::sort(v.begin(), v.end(), boost::bind(compare, _1, _2)); 
} 


因为sort需要的是二元函数,所以要用两个占位符。

boost::ref
当bind中函数参数是引用的时候,就要使用boost::ref传入:
#include <boost/bind.hpp> 
#include <iostream> 
#include <vector> 
#include <algorithm> 

void add(int i, int j, std::ostream &os) 
{ 
  os << i + j << std::endl; 
} 

int main() 
{ 
  std::vector<int> v; 
  v.push_back(1); 
  v.push_back(3); 
  v.push_back(2); 

  std::for_each(v.begin(), v.end(), boost::bind(add, 10, _1, boost::ref(std::cout))); 
} 


由于bind的参数专递是按值传递的,如果直接传递std::cout,函数将会创建cout的一个拷贝,所以我们要用boost::ref来传递引用。常量引用用boost::cref传递。

boost::function:
boost中用function来封装函数指针,function的用法如下:
include <boost/function.hpp> 
#include <iostream> 
#include <cstdlib> 
#include <cstring> 

int main() 
{ 
  boost::function<int (const char*)> f = std::atoi; 
  std::cout << f("1609") << std::endl; 
  f = std::strlen; 
  std::cout << f("1609") << std::endl; 
} 


如果f未赋予一个函数或者为0是被调用,则会抛出boost::bad_function_call 异常。

类的成员函数也可使用function,但是调用的时候要传入一个对象:
#include <boost/function.hpp> 
#include <iostream> 

struct world 
{ 
  void hello(std::ostream &os) 
  { 
    os << "Hello, world!" << std::endl; 
  } 
}; 

int main() 
{ 
  boost::function<void (world*, std::ostream&)> f = &world::hello; 
  world w; 
  f(&w, boost::ref(std::cout)); 
} 


boost::lambda:
lambda函数又称匿名函数,他的目的是令代码更为紧凑,也更容易理解。
#include <boost/lambda/lambda.hpp> 
#include <iostream> 
#include <vector> 
#include <algorithm> 

int main() 
{ 
  std::vector<int> v; 
  v.push_back(1); 
  v.push_back(3); 
  v.push_back(2); 

  std::for_each(v.begin(), v.end(), std::cout << boost::lambda::_1 << "\n"); 
} 


Boost.Lambda 提供了几个结构来定义匿名函数。 代码就被置于执行的地方,从而省去将它包装为一个函数再进行相应的函数调用的这些开销。 与原来的例子一样,这个程序将容器 v 的所有元素写出至标准输出流。

注意lambda中也定义了三个占位符,这些占位符在boost::lambda命名空间中。

lambda有一个缺点,在语句中必须用'\n'代替std::endl才能成功编译。这是由于std::endl的类型与lambda函数 std::cout << boost::lambda::_1 不一致,所以不能使用它。

在lambda中海定义了几个if结构,比如if_then,我们看一个例子:
#include <boost/lambda/lambda.hpp> 
#include <boost/lambda/if.hpp> 
#include <iostream> 
#include <vector> 
#include <algorithm> 

int main() 
{ 
  std::vector<int> v; 
  v.push_back(1); 
  v.push_back(3); 
  v.push_back(2); 

  std::for_each(v.begin(), v.end(), 
    boost::lambda::if_then(boost::lambda::_1 > 1, 
    std::cout << boost::lambda::_1 << "\n")); 
}


boost::lambda::if_then() 模板函数,它要求两个参数:第一个参数对条件求值 - 如果为真,则执行第二个参数。 如例中所示,每个参数本身都可以是 lambda 函数。

除了 boost::lambda::if_then(), Boost.Lambda 还提供了 boost::lambda::if_then_else() 和 boost::lambda::if_then_else_return() 模板函数 - 它们都要求三个参数。 另外还提供了用于实现循环、转型操作符,甚至是 throw - 允许 lambda 函数抛出异常 - 的模板函数。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics