lambda宏如何创建lambda?


20

我在GitHub上找到了这段代码,但不太了解:

#define lambda(ret_type, _body) ({ ret_type _ _body _; })

然后:

int (*max)(int, int) = lambda(int,
                             (int x, int y) {
                                 return x > y ? x : y;
                             });

int max_value = max(1, 2);
// max_value is 2

内的下划线是什么#define?它如何返回函数指针?


7
您是否尝试过仅扩展宏(例如使用gcc -E)来查看其作用?
无用的

5
请查看扩展文件godbolt.org/z/C5TLWj尽管结果不容易理解
Eugene Sh。

2
我假设您是根据获得此代码的地方的注释知道的,但这确实依赖于GCC扩展的嵌套函数。
Thomas Jager

4
@EugeneSh。它通过使用GCC的嵌套函数来初始化函数指针。原始代码是从这里开始的。该项目今天在Hacker News上共享。
Thomas Jager

4
@EugeneSh。它是两个GCC扩展的组合:嵌套函数和expression中的复合语句。嵌套函数出现在复合语句内。
Interjay

Answers:


10

使用这个宏,

int (*max)(int, int) = lambda(int,
                             (int x, int y) {
                                 return x > y ? x : y;
                             });

扩展为:

int (*max)(int, int) = ({
    int _ (int x, int y) { return x > y ? x : y; }
    _;
});

在花括号中,这使用GCC的嵌套函数来创建执行所需操作的函数。在内部范围内,它具有名称_

然后,正如interjay所指出的,使用了GCC的Statement Expressions。有效地,该函数_被分配给指针max

如果不使用这样的宏,则可以用不同的方式编写并用作:

int val1 = 4;
int val2 = -30;

int perform_operation(int (*op)(int, int)) {
    int new_val = op(val1, val2);
    val1 = val2;
    val2 = new_val;
    return new_val;
}

int enclosing_function (void) {
    // Create max "lambda"
    int (*max)(int, int);
    {
        // Curly braces limit the scope of _
        int _ (int x, int y) { return x > y ? x : y; }
        max = _;
    }

    return perform_operation(max);
}

此代码示例中可以比较三种方法。


宏不会执行任何操作,因为它将无法在gcc中进行编译
P__J__

@P__J__它确实编译ideone.com/T5FLXb
Eugene Sh。

@P__J__我在回答的末尾添加了一个示例,该示例还显示了此宏的使用情况。
Thomas Jager

你为什么不能max(4, -30);代替apply_binary_op(max, 4, -30);呢?
SS安妮

1
“表达式中的复合语句”称为“语句表达式”。具有可以(例如)分配给某物的值的语句。
彼得·科德斯

7

这称为语句表达式,并创建一个“ lambda”(或嵌套函数)并返回指向它的指针。它是GNU C特定的。

宏扩展为:

int (*max)(int, int) = ({ int _ (int x, int y) { return x > y ? x : y; } _; })

所述_在端部是像return

下划线实际上是创建并“返回”的函数的名称。之所以使用它,是因为它是一个不常用的标识符(有充分的理由;_很可能是描述性最低的标识符)。

使用语句表达式的原因_不会在语句表达式的范围退出后定义。

因此,通过宏:

#define lambda(ret_type, _body) ({ ret_type _ _body _; })

ret_type是“ lambda”的返回类型。_是其中使用的函数的名称,因为它是一个不常用的标识符名称。_body由参数和函数主体组成。尾随_“返回”“ lambda”。

可以在Let's Destroy C(合适的名称)中找到此代码。你不应该使用它。这将使您的代码仅在支持GNU C扩展的编译器上工作。相反,只需编写一个函数或宏。

如果您经常使用这种构造或想要更多功能,则建议使用C ++。使用C ++,您可以执行与此类似的操作拥有可移植的代码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.