C++模板仿函数

Zee*_*aja 1 c++ stl functor visual-studio

我想知道是否有人可以用仿函数帮助我.我真的不明白是什么算子以及它们是如何工作的我已经尝试使用谷歌搜索它但我仍然没有得到它.仿函数如何工作以及它们如何使用模板

ark*_*rke 6

仿函数基本上是一个"函数对象".它是一个包含在类或结构中的单个函数,您可以将其传递给其他函数.

它们通过创建自己的类或结构来工作,该类重载函数调用操作符(称为operator()).通常,您可以通过简单地将其作为函数的参数构建它来创建它的实例,该函数使用仿函数.

假设您有以下内容:

std::vector<int> counts;
Run Code Online (Sandbox Code Playgroud)

现在,您想要增加该向量中包含的所有计数.您可以手动循环它们以递增它们,或者您可以使用仿函数.在这种情况下,合适的函子看起来像这样:

struct IncrementFunctor
{
    int operator() (int i)
    {
        return i + 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

IncrementFunctor现在是一个函子,它接受任何整数并递增它.要将它应用于计数,可以使用std :: transform函数,它将仿函数作为参数.

std::transform(
    counts.begin(),       // the start of the input range
    counts.end(),         // the end of the input range
    counts.begin(),       // the place where transform should place new values. 
                          // in this case, we put it right back into the original list.
    IncrementFunctor());  // an instance of your functor
Run Code Online (Sandbox Code Playgroud)

语法IncrementFunctor()创建该仿函数的一个实例,然后直接传递给std :: transform.当然,您可以将实例创建为局部变量并将其传递,但​​这样更方便.

现在,进入模板.std :: transform中的仿函数类型是模板参数.这是因为std :: transform不知道(或关心!)你的仿函数是哪种类型.所有它关心的是它有一个适合的operator()定义,它可以做类似的事情

newValue = functor(oldValue);
Run Code Online (Sandbox Code Playgroud)

编译器对模板非常聪明,并且通常可以自己弄清楚模板参数是什么.在这种情况下,编译器会自动实现您传入的类型为IncrementFunctor的参数,该参数在std :: transform中定义为模板类型.它对列表也是如此,因此编译器会自动识别实际调用如下所示:

std::transform<std::vector<int>::iterator, // type of the input iterator
               std::vector<int>::iterator, // type of the output iterator
               IncrementFunctor>(          // type of your functor
    counts.begin(),       // the start of the input range
    counts.end(),         // the end of the input range
    counts.begin(),       // the place where transform should place new values. 
                          // in this case, we put it right back into the original list.
    IncrementFunctor());  // an instance of your functor
Run Code Online (Sandbox Code Playgroud)

它可以节省你很多的打字.;)


tpd*_*pdi 5

仿函数是可以使用函数调用运算符调用/调用的东西,通过附加语法(),可选地在括号内包含参数列表.

这都是模板需求.就模板而言,调用它的东西是允许这种语法的任何东西 - 换句话说,就是自由函数或覆盖的类的实例operator()().("自由"函数只是一个不是成员的函数,也就是说,它是全局范围内的函数或以前包含的命名空间范围内的函数.)

在模板元编程之外,我们通常不会说自由函数是一个函子,并为一个覆盖的类的实例保留该名称operator()():

struct Foo {
 public:
   void operator()( int i ) { // do something }
   void operator()( int i, char x ) { // do something else }
}
Run Code Online (Sandbox Code Playgroud)

在C++模板中进行编译,因此只要语法有意义,编译器就会愉快地使用函数或函子:

template<typename T> class Bar {
  private int j ;
  public:
    Bar( int i ) : j(i) {}
    void doIt(T t) {
     t( j ) ;
  }
}

Foo f;
extern void resize( int i ) ; // in some header

Bar<Foo> bf( 5 ) ;
// a Bar that is templated on Foo
Bar< void (&)(int)   > br( 5 ) ; 
// a Bar that is templated on a function taking int and returning void

br.doit( &resize ) ; // call resize with br.j
bf.doit( f ) ; // call Foo::operator()(int) on Foo f with bf.j
Run Code Online (Sandbox Code Playgroud)