C++轮子 · 函数式编程

发布时间:2024年01月19日

和算法配套出现的组件除了迭代器之外还有仿函数,这篇文章会重点介绍仿函数的使用以及和它相关的函数式编程工具。

仿函数

算法库中有很多算法都有一个重载的版本,接收一个Callable object用于提升算法的灵活性。

template< class InputIt, class UnaryPredicate >
InputIt find_if( InputIt first, InputIt last,
                 UnaryPredicate p );

template< class InputIt, class T, class BinaryOperation >
T accumulate( InputIt first, InputIt last, T init,
              BinaryOperation op );

语法上可调用对象(Callable object)是指可以使用函数调用符号操作它的任何对象,它可以表示很多对象,比如普通的函数,也比如一个重载了函数调用符的类型对象。如果可调用对象的返回值是bool则称之为Predicate(有人翻译成谓词)。接收Predicate的算法通常都以_if结尾,比如:std::find_ifstd::copy_if

我们把重载了函数调用符的对象称为仿函数,它在功能上是一个函数,在语法上是一个类。它和普通函数最大的区别是它可以保存内部状态。

假如我们现在要找出第一个奇数,我们可以这样写:

bool is_odd(int a) { return a % 2; }
std::find_if(std::begin(a), std::end(a), is_odd)

假如我们要查找第一个偶数,我们可以写成这样:

bool is_even(int a) { return !is_odd(a); }
std::find_if(std::begin(a), std::end(a), is_even)

但是如果我实现成仿函数,我们可以这样写:

class FindOdd {
public:
    NumberPredicate(bool found_odd) { ... }

    bool operator()(int a) const {
        if (found_odd_) {
            ...
        }

        ...
    }

private:
    bool found_odd_;
};

std::find_if(std::begin(a), std::end(a), FindOdd(true));
std::find_if(std::begin(a), std::end(a), FindOdd(false));

上面这个例子其实并不太恰当,我不推荐在一个函数中实现两个功能,但是它展示了仿函数区别于普通函数的重要特性——可以保存状态。

Predicate 应该是纯函数

Predicate是指返回值为boolCallable object,而纯函数是指这个对象不会有side effect,也就是说如果以同样的参数调用这个对象,结果是一样的。之所以这么建议是因为Predicate作为算法的参数而存在,而参数的传递是值拷贝,如果Predicate<

文章来源:https://blog.csdn.net/chenyuping333/article/details/135698078
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。