0

我有一个简单的问题,但我不知道如何解决它,因为我从未在 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;
}

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

非常感谢你 !

4

2 回答 2

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::lessand std::greater,所以我上面给出的less_thanand函子并不是真正必要的。greater_than不幸的是,它们只是进行比较,所以要像我们在这里一样使用它们,你必须使用std::bind1storstd::bind2nd让它们与一个常数进行比较:

std::remove_copy_if(src.begin(),
                    src.end(),
                    std::ostream_iterator<int>(std::cout, "\n"),
                    std::bind1st(std::less<int>(), 10));
于 2012-04-04T03:54:49.683 回答
1
void applyFunction(std::function<void(double, double)>);
// ...
applyFunction(std::bind(&OtherClass::myFunction1, &otherClass));
于 2012-04-04T03:23:52.037 回答