C ++:一个菜鸟的Functors和std :: function

时间:2012-04-04 03:16:46

标签: c++ functor std-function

我有一个简单的问题,但我不知道如何解决它,因为我从未在C ++中使用过仿函数。

我想做那样的事情(这只是一个例子):

class MyClass
{
    void applyFunction(myFunction);  /* WRONG SYNTAX */
    double *_x;
    unsigned int *_size;
};

void MyClass::applyFunction(myFunction) /* WRONG SYNTAX */
{
    for (unsigned int i = 0; i < _size; ++i)
        myFunction(_x[i], 10.);
}

class OtherClass
{
    void myFunction1(double x, double lim);
    void myFunction2(double x, double lim);
    std::vector _v;
};

void OtherClass::myFunction1(double x, double lim)
{
    _v.clear();
    if (x > lim)
        _v.push_back(x);
}

void OtherClass::myFunction2(double x, double lim)
{
    _v.clear();
    if (x < lim)
        _v.push_back(x);
}

int main()
{
    MyClass myClass;
    OtherClass otherClass;
    myClass.applyFunction(otherClass.myFunction1); /* WRONG SYNTAX */
    std::cout<<otherClass._v.size()<<std::endl;
    myClass.applyFunction(otherClass.myFunction2); /* WRONG SYNTAX */
    std::cout<<otherClass._v.size()<<std::endl;
        return 0;
}

使用functor / std :: functions的正确语法是什么?

非常感谢!

2 个答案:

答案 0 :(得分:4)

我会告诉你你想要使用仿函数。只是为了笑容,我还假设你想要以“正确”的方式做到这一点,而不仅仅是找到一个可以让它编译的语法(并且可能运行,也许可以做你想要的)。

在这种情况下,标准库已经有了算法来支持你正在做的很多事情(特别是在C ++ 11中)。要将符合某些条件的数据复制到目标向量中,您需要std::copy_if(尽管在C ++ 98/03中缺少这一点 - 您必须颠倒比较的意义并使用std::remove_copy_if

使用它,你的代码就像这样:

template <class T>
class less_than {
    T limit;
public:
    less_than(T lim) : limit(lim) {}
    bool operator()(T const &val) { return val < limit; }
};

std::copy_if(source.begin(), 
             source.end(), 
             std::back_inserter(target), 
             less_than<int>(10));

但是,如果你有C ++ 11可用,那么使用lambda可能更方便:

std::copy_if(source.begin(), 
             source.end(), 
             std::inserter(target), 
             [](int v) { return v < 10;});

lambda基本上只是让编译器为你生成一个匿名仿函数类的一种方式,所以两者之间没有太大的区别,但lambda显然可以节省相当多的输入。

如果你坚持使用C ++ 03,你基本上只是反转比较:

template <class T>  
class greater_than { 
    T limit;
public:
    bool operator()(T const &val) {
        return val > limit;
    }
};

std::remove_copy_if(src.begin(), 
                    src.end(), 
                    std::back_inserter(dst),
                    greater_than(10));

或者,您可以非常轻松地编写自己的copy_if - 它主要是通过监督而被排除在C ++ 98/03之外,而不是因为它需要语言无法提供的任何内容,或类似的内容(虽然我记得,完全正确地处理所有边界条件可能有点棘手)。

对于它的价值,我还应该注意标准库确实有std::lessstd::greater,所以我上面给出的less_thangreater_than仿函数都是真的很有必要。不幸的是,他们只是进行比较,所以要像我们在这里一样使用它们,你必须使用std::bind1ststd::bind2nd来比较常量:

std::remove_copy_if(src.begin(),
                    src.end(),
                    std::ostream_iterator<int>(std::cout, "\n"),
                    std::bind1st(std::less<int>(), 10));

答案 1 :(得分:1)

void applyFunction(std::function<void(double, double)>);
// ...
applyFunction(std::bind(&OtherClass::myFunction1, &otherClass));