2012-01-13 4 views
0

Могут ли функторы быть определены локально внутри тела функции?Определение функтора внутри тела кода

Одно из возможных применений для локально определенных функторов я могу думать, (особенно, если мы хотим использовать алгоритмы STL), это сказать

мы имеем два вектора std::vector<int> «S a и b тогда мы можем рассмотреть их в равной во многих отношениях. то есть 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++ вы используете? Если он будет достаточно новым, возможно, что лямбда будет для вас вариантом. – JaredPar

+0

Возможный дубликат [Почему код с использованием локальной структуры как параметра для функции STL не компилируется в g ++?] (Http://stackoverflow.com/questions/4569928/why-code-using-local-struct-as-parameter-for -stl-function-does-not-compile-in-g) –

+0

Возможный дубликат [Что такое лямбда-выражение в C++ 11?] (http://stackoverflow.com/questions/7627098/what-is-a -lambda-expression-in-c11) – Flexo

ответ

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

You может наследовать ваш функтор из базового класса шаблона, определенного в области верхнего уровня, а затем ссылаться только на базовый класс (например, с помощью 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) 
    ); 
    ... 
} 
Смежные вопросы