在代码体内定义仿函数

时间:2012-01-13 00:20:17

标签: c++

可以在函数体内局部定义函子吗?

我能想到的本地定义仿函数的一种可能用途(特别是如果我们想使用STL算法),可以说是

我们有两个向量std::vector<int>的{​​{1}}和a,然后我们可以在很多方面对它们进行相同的考虑。即b,其中loop_counter不断变化,我们在每次循环迭代中测试它​​们是否相等。

a[i] = b[i] (mod 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 } 之前移动仿函数定义,干净地编译代码并正确执行。

因此,即使在函数体内定义一个仿函数似乎是不可能的,我想要一些好的STL就像在每次迭代中改变相等条件一样。

3 个答案:

答案 0 :(得分:1)

如果你可以使用C ++ 11,那就行了。在C ++ 03中,您不能使用本地类作为模板参数。您可以使用std::accumulate代替本地类静态函数(以及用于存储结果的非本地结构):

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 :(得分:1)

(假设你被困在C ++ 03中。)

您可以让您的仿函数继承自顶级作用域中定义的模板基类,然后仅引用基类(例如,使用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)
    );
    ...
}

答案 2 :(得分: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]))
    {
        ...
    }
}