C ++:如何从另一个谓词定义泛型非谓词

时间:2018-06-01 15:58:20

标签: c++

假设我有一个谓语:

bool my_pred(const MyType* x) {
    ....
}

我想过滤一些集合,因此它只包含与my_pred不匹配的元素。理想情况下,我想写这样的东西:

using namespace std;
vector<const MyType*> elems = ...;
remove_if(begin(elems), end(elems), not(my_pred));

如何编写上面的not高阶函数?

目标是实现以下目标(但这段代码当然不起作用):

template<typename T>
function<bool(T)> not(function<bool(T)> pred) {
    return [&](T x) { return !pred(x) };
}

我尝试使用std::logical_not,但我失败了。我希望每次想要做这样的事情时都要避免定义一个特定的lambda。

理想情况下,我想将此模式扩展到其他逻辑运算符。 也许有更好的方法来做到这一点?

谢谢!

1 个答案:

答案 0 :(得分:2)

使用

template<typename T>
function<bool(T)> not(function<bool(T)> pred) {
    return [&](T x) { return !pred(x) };
}

你通过引用捕获,但lambda生命长于捕获pred,导致悬空指针和UB。

您应该通过复制或移动来捕获:

template<typename T>
function<bool(T)> not(function<bool(T)> pred) {
    return [=](T x) { return !pred(x) };
}

你可以通过更通用来消除std::function的开销:

template<typename F>
auto not(F pred) {
    return [=](auto&& x) { return !pred(x); };
}

(要求C ++ 14)。