Skip to content

Instantly share code, notes, and snippets.

@koturn
Last active April 15, 2022 02:34
Show Gist options
  • Save koturn/5013105 to your computer and use it in GitHub Desktop.
Save koturn/5013105 to your computer and use it in GitHub Desktop.
C言語におけるラムダを関数マクロで実現したものです。 GNU拡張文法(複文の式化、関数内の関数定義)を用いているので、gccでしか用いることができません。 また、トップレベルで用いることも不可能です。 C++でもコンパイルエラーにならないように、C++0xのラムダに変換するようにしています。 利便性を考え、ある程度の省略表記を許すようにしています。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*!
* @brief GNU拡張機能を用いたラムダ関数を実現するマクロ
*
* gccもしくはC++0x対応コンパイラでのみコンパイル可能<br>
* トップレベルで用いることはできない
* @param [in] rettype 返り値の型
* @param [in] ARG_LIST 関数の引数.丸括弧が必要
* @param [in] BODY 関数本体。中括弧が必要
* @return 定義した無名関数へのポインタ
*/
#if defined(__cplusplus) // C++は、C++0xのラムダを用いる
# define LAMBDA(rettype, ARG_LIST, BODY) \
([&]ARG_LIST -> rettype { BODY; } )
#elif defined(__GNUC__) && !defined(__clang__)
# define LAMBDA(rettype, ARG_LIST, BODY) \
({ \
rettype __lambda_funcion__ ARG_LIST { BODY; } \
__lambda_funcion__; \
})
#endif
/*!
* @brief プログラムのエントリポイント
* @return 終了コード
*/
int main(void) {
int i;
int array[5] = {4, 1, 7, -2, 3};
int len;
// 関数ポインタに無名関数を渡す例
int (*sum)(int, int, int) = LAMBDA(int, (int a, int b, int c), {
return a + b + c;
});
// 関数ポインタに格納した無名関数を呼び出す
printf("2 + 3 + 5 = %d\n", sum(2, 3, 5));
// その場で無名関数を呼び出す例1
len = LAMBDA(int, (const char *str1, const char *str2), {
return strlen(str1) - strlen(str2);
})("Hello", "World!");
printf("difflen = %d\n", len);
// その場で無名関数を呼び出す例2
printf("6 - 1 = %d\n", LAMBDA(int, (int a, int b), {
return a - b;
})(6, 1));
// qsort()関数の第4引数に渡す例
qsort(array, (sizeof(array) / sizeof(array[0])), sizeof(array[0]),
LAMBDA(int, (const void *a, const void *b), {
return *(int *)a - *(int *)b;
})
);
for (i = 0; i < (sizeof(array) / sizeof(array[0])); i++) {
printf("array[%d] = %d\n", i, array[i]);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment