2012-01-13 20 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) 
    ); 
    ... 
}