C++轮子(5) · 函数式编程

本文介绍了C++中的函数式编程,重点讲解了仿函数的概念和使用,强调仿函数可以保存内部状态。同时,讨论了Predicate应作为纯函数的原因,并引入了C++11的lambda表达式,阐述其简化代码和创建闭包的能力。还提到了std::function和std::bind在处理回调和多态函数对象存储上的应用。
摘要由CSDN通过智能技术生成

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

仿函数

算法库中有很多算法都有一个重载的版本,接收一个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不是纯函数,而算法内部实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值