将运算符传递给 Lambda 函数

3

是否可以将运算符传递给lambda表达式?例如,将某个运算符op传递给下面的函数。

auto lambdaCompare = [](value,compare1,compare2,op){return value op compare1 and value op compare2;};

请注意,此处保留了HTML标签。

你是指 std::multiplies 和类似的函数吗? - Mooing Duck
我正在尝试创建一个多用途的lambda函数来进行比较,例如如果操作符是">="或"<="。 - tswanson-cs
对于这种情况,您可以传递一个函数对象而不是 op。然后在函数体中,您可以返回 op(value, compare1, compare2) 或类似的内容。 - TonySalimi
std::greater_equal是一个C++标准库中的函数对象,用于比较两个值是否相等或者第一个值是否大于等于第二个值。 - Mooing Duck
3个回答

5
您不能传递运算符并像您想要的那样使用它,但您可以传递 std::greater_equal
#include <iostream>
#include <functional>

int main() {

    auto lambdaCompare = [](int value, int compare1, int compare2, std::function<bool(int, int)> op) {
        return op(value, compare1) && op(value, compare2);
    };

    std::cout << lambdaCompare(2, 1, 6, std::greater_equal<int>());

    return 0;
}

这正是我想要做的。谢谢你。 - tswanson-cs
4
虽然你可以这样做,但实际上应该更倾向于使用通用的 C++14 lambda 函数,避免使用 std::function 带来的额外开销(间接引用会导致内联失败并破坏优化机会)。 - Deduplicator
那么,是否最好分别为std::greater_equal和std::less_equal创建一个函数,而不必发送操作符呢? - tswanson-cs

3

我会这样做:

C++14

auto l = [](auto value, auto c1, auto c2, auto op)
{
    return (op(value, c1) && op(value, c2));
};

l(1, 2, 3, [](int a, int b) { return a < b; });

C++11

auto l = [](int value, int c1, int c2, bool(* op)(int, int))
{
    return (op(value, c1) && op(value, c2));
};

l(1, 2, 3, [](int a, int b) { return a < b; });

嗯,你也可以这样做:

我对于是否推荐这样做感到矛盾。一方面,它是一个宏,不好理解;另一方面,它看起来很简单,容易理解。

C++14

auto l = [](auto value, auto c1, auto c2, auto op)
{
    return (op(value, c1) && op(value, c2));
};

l(1, 2, 3, OPERATOR(<));
l(1, 2, 3, OPERATOR(<=));
l(1, 2, 3, OPERATOR(>));
l(1, 2, 3, OPERATOR(>=));
l(1, 2, 3, OPERATOR(==));
l(1, 2, 3, OPERATOR(!=));

使用

#define OPERATOR(op) [] (const auto& a, const auto& b) { return a op b; }

C++11

auto l = [](int value, int c1, int c2, Op_t<int, int, bool> op)
{
    return (op(value, c1) && op(value, c2));
};

l(1, 2, 3, OPERATOR(int, int, <));
l(1, 2, 3, OPERATOR(int, int, <=));
l(1, 2, 3, OPERATOR(int, int, >));
l(1, 2, 3, OPERATOR(int, int, >=));
l(1, 2, 3, OPERATOR(int, int, ==));
l(1, 2, 3, OPERATOR(int, int, !=));

使用

#define OPERATOR(T1, T2, op) [] (const T1& a, const T2& b) { return a op b; }

template <class T1, class T2, class R>
using Op_t = auto (*) (const T1&, const T2&) -> R;

2
如果您的操作符是自由函数,您可以回退到类似以下的方法:
struct S
{
public:
    S(int i) : i (i) {}
    int i;
};

bool operator < (const S& s1, const S& s2)
{
    return s1.i < s2.i;
}

int main()
{
    auto lambda_compare = [](S s1, S s2, auto op) {
        return op(s1, s2);
    };
    bool b = lambda_compare(S(1), S(2), operator<);
    return 0;
}

最好使用lambda,因为operator<的重载集很少是单一的。这样可以避免函数指针,促进内联。不幸的是,通用lambda在C++14中首次亮相,而不是C++11。 - Deduplicator

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接