половые акты с препроцессором в необычных позах |
[Aug. 25th, 2013|10:54 am] |
ПРЕДУПРЕЖДЕНИЕ: кто ходит в гости по утрам использует такой код — гад, скотина, мудак и долбоёб.
Итак. Есть у нас язык «C». Делаем мы на нём какую-то унылую ерунду, и хотим мы, чтобы конструктор некоторого объекта (пусть это будет «бесполезная точка») существовал в трёх вариантах: без аргументов, с одним аргументом и с двумя аргументами. Можно, конечно, каждый раз руками делать что-то типа point_new_empty(), point_new_x(x), point_new_xy(x, y). А можно сделать извращение и поабузить препроцессор. Вот так, например:
#define _X_VA_XARGS_IMPL(_1, _2, _3, _4, N, …) N #define _X_VA_XARGS(…) _X_VA_XARGS_IMPL(__VA_ARGS__, _bad, _2a, _1a, _0a)
#define _X_POINT_NEW_IMPL2(_pfx,_sfx, …) _pfx ## _sfx (__VA_ARGS__) #define _X_POINT_NEW_IMPL(_pfx,_sfx, …) _X_POINT_NEW_IMPL2(_pfx,_sfx, __VA_ARGS__) #define point_new(…) _X_POINT_NEW_IMPL(point_new, _X_VA_XARGS(_nothing_, ##__VA_ARGS__), __VA_ARGS__)
#include <stdio.h> #include <stdlib.h>
static void point_new_0a (void) { printf("point_new(undef, undef)\n"); } static void point_new_1a (int n0) { printf("point_new(%d, undef)\n", n0); } static void point_new_2a (int n0, int n1) { printf("point_new(%d, %d)\n", n0, n1); }
int main () { point_new(); point_new(42); point_new(42, 666); return 0; }
да-да-да, я знаю: извращенцы отаке. Но работает. Ах, да: учтите, что трюк «##__VA_ARGS__» — это специфичная для гнутого препроцессора фича. Без этой фичи отдетектить отсутствие аргументов тоже можно, но ебанётесь на отличненько.
Для тех, кто не врубился, отчего так дохуя макросов: специфика препроцессорной «развёртки», так надо. Читайте доки, они рулят. А кто не использует gcc — тот сам дурак и пусть сосёт бензин. |
|
|