2012-01-13 66 views
0

函数体可以在函数体内本地定义吗?在代码体内定义仿函数

为本地定义函子我能想到的,(特别是如果我们想用STL算法),是说

我们有两个向量std::vector<int>ab一个可能的用途话,可以考虑他们平等在许多方面。即a[i] = b[i] (mod loop_counter)其中loop_counter不断变化,我们测试它们在每次循环迭代中的相等性。

for(int i=0 ; i<=10 ; ++i) 
{ 
//Define binary predicate functor my_local_predicate 

//Test for equality using functor local to loop 
std::equal(a.begin(), a.end(), b.begin, my_local_predicate) 

// Do something if they are equal OR unequal 

} 

如果答案是否定的,那么对于平等的条件在每次迭代中不断变化的情况,上述方法将如何进行?

注意:我试着定义一个仿函数如下(这里没有for循环)但程序无法编译。

#include <algorithm> 
#include <iostream> 
#include <list> 



int main() { 

    class EvenOddFunctor 
    { 
    int even_; 
    int odd_; 
    public: 
    EvenOddFunctor() : even_(0), odd_(0) {} 
    void operator()(int x) { 
     if (x%2 == 0) even_ += x; 
     else odd_ += x; 
    } 
    int even_sum() const { return even_; } 
    int odd_sum() const { return odd_; } 
    }; 

    EvenOddFunctor evenodd; 

    int my_list[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 
    evenodd = std::for_each(my_list, 
        my_list+sizeof(my_list)/sizeof(my_list[0]), 
        evenodd); 

    std::cout << "Sum of evens: " << evenodd.even_sum() << "\n"; 
    std::cout << "Sum of odds: " << evenodd.odd_sum() << std::endl; 

    // output: 
    // Sum of evens: 30 
    // Sum of odds: 25 
} 

main()代码编译干净,并正确地执行之前移动所述算符定义。

所以,即使在一个函数体内定义一个仿函数似乎是不可能的,我还是希望能够在每次迭代中改变相等条件的方式来实现一些不错的STL。

+1

您正在使用哪种C++编译器?如果它足够新,那么lambda可能是您的一个选择。 – JaredPar 2012-01-13 00:22:39

+0

[为什么使用本地结构作为STL函数参数的代码不能在g ++中编译?](http://stackoverflow.com/questions/4569928/why-code-using-local-struct-as-parameter-for -stl-function-does-not-compile-in-g) – 2012-01-13 00:23:09

+0

可能的重复[什么是C++ 11中的lambda表达式?](http://stackoverflow.com/questions/7627098/what-is-a -lambda-expression-in-c11) – Flexo 2012-01-13 00:23:32

回答

0

对于你的问题的第一部分,我没有看到如何有一个本地定义的功能是必要的。你需要的只是一种选择不同功能的方法,这很简单。例如:

std::function<bool(int,int)> my_functions[10]; 
my_functions[0] = std::equal_to<int>(); 
my_functions[1] = both_divisible_by_5; 
...etc 

for (int i=0; i<10; ++i) 
{ 
    if (std::equal(a.begin(), a.end(), b.begin, my_functions[i])) 
    { 
     ... 
    } 
} 
1

如果你可以使用C++ 11,这只是工作。在C++ 03中,你不能使用本地类作为模板参数。你可以使用std::accumulate,而不是与本地类的静态函数(和非本地结构来存储结果):(假设你被困在C++ 03)

struct EvenOdd 
{ 
    int even; 
    int odd; 
    static EvenOdd empty() { EvenOdd result= { }; return result; } 
}; 

int main() 
{ 
    struct EvenOddFunctor 
    { 
     static EvenOdd function(const EvenOdd &old_result, int x) 
     { 
      EvenOdd result= old_result; 
      if (x%2 == 0) result.even += x;   
      else result.odd += x; 
      return result; 
     } 
    }; 

    EvenOdd evenOdd= std::accumulate(..., EvenOdd::empty(), EvenOddFunctor::function); 
} 
1

你可以让您的函数继承自顶层作用域中定义的模板基类,然后仅引用基类(例如,使用mem_fun/bind1st)。

template <typename T> 
struct val_functor { 
    virtual ~val_functor() {} 
    virtual void operator()(T x) = 0; 
}; 

int main() 
{ 
    class EvenOddFunctor : public val_functor<int> 
    ... 
    std::for_each(my_list, my_list+sizeof(my_list)/sizeof(my_list[0]), 
     std::bind1st(
      std::mem_fun(&val_functor<int>::operator()), 
      (val_functor<int>*)&evenodd) 
    ); 
    ... 
}