#include <stdio.h>
#include <string.h>
static int hashfunc(int a, const char *b, size_t length)
{
printf("hashfunc(%i, %.*s, %zu)\n", a
, length
, b
, length
); return 4;
}
// Вариант 1: "Мааам, у меня паттерн-матчинг!".
#define cat_12_(x, ...) x ## __VA_ARGS__
#define choose_2_(x, v, ...) v
#define choose_(p, ...) choose_2_(__VA_ARGS__, p,)
#define hash(a, b, c) hashfunc(a, b, choose_(c, cat_12_(hash_, c(b))))
#define hash_0 , -1+sizeof
static void test1(void)
{
const char *foo = "abcdef";
char *bar = "abcdef";
hash
(1, foo
, strlen(foo
)); // strlen hash
(2, bar
, strlen(bar
)); // strlen hash(3, "abcdef", 0); // sizeof
// Ниработает: матчится только литерал 0.
// hash(1, "abcdef", 0x00);
// Ниработает: ограничения на склейку токенов.
// hash(1, foo, +strlen(foo));
}
#undef hash
// Вариант 2: современный, хипстерский - по мере сил проверяется тип.
#define hash(a, b) _Generic((b), \
const char[sizeof(b)]: hashfunc(a, b, sizeof(b) - 1),\
char[sizeof(b)]: hashfunc(a, b, sizeof(b) - 1),\
default: hashfunc(a, b, strlen(b)))
static void test2(void)
{
const char *foo = "abcdef";
char *bar = "abcdef";
char baz[] = "abcdef";
hash(1, foo); // strlen
hash(2, bar); // strlen
hash(3, baz); // sizeof
hash(4, "abcdef"); // sizeof
}
int main(void)
{
test1();
test2();
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KCnN0YXRpYyBpbnQgaGFzaGZ1bmMoaW50IGEsIGNvbnN0IGNoYXIgKmIsIHNpemVfdCBsZW5ndGgpCnsKICAgIHByaW50ZigiaGFzaGZ1bmMoJWksICUuKnMsICV6dSlcbiIsIGEsIGxlbmd0aCwgYiwgbGVuZ3RoKTsKICAgIHJldHVybiA0Owp9CgovLyDQktCw0YDQuNCw0L3RgiAxOiAi0JzQsNCw0LDQvCwg0YMg0LzQtdC90Y8g0L/QsNGC0YLQtdGA0L0t0LzQsNGC0YfQuNC90LMhIi4KCiNkZWZpbmUgY2F0XzEyXyh4LCAuLi4pIHggIyMgX19WQV9BUkdTX18KI2RlZmluZSBjaG9vc2VfMl8oeCwgdiwgLi4uKSB2CiNkZWZpbmUgY2hvb3NlXyhwLCAuLi4pIGNob29zZV8yXyhfX1ZBX0FSR1NfXywgcCwpCiNkZWZpbmUgaGFzaChhLCBiLCBjKSBoYXNoZnVuYyhhLCBiLCBjaG9vc2VfKGMsIGNhdF8xMl8oaGFzaF8sIGMoYikpKSkKI2RlZmluZSBoYXNoXzAgLCAtMStzaXplb2YKCnN0YXRpYyB2b2lkIHRlc3QxKHZvaWQpCnsKICAgIGNvbnN0IGNoYXIgKmZvbyA9ICJhYmNkZWYiOwogICAgY2hhciAqYmFyID0gImFiY2RlZiI7CgogICAgaGFzaCgxLCBmb28sIHN0cmxlbihmb28pKTsgLy8gc3RybGVuCiAgICBoYXNoKDIsIGJhciwgc3RybGVuKGJhcikpOyAvLyBzdHJsZW4KICAgIGhhc2goMywgImFiY2RlZiIsIDApOyAgICAgIC8vIHNpemVvZgoKICAgIC8vINCd0LjRgNCw0LHQvtGC0LDQtdGCOiDQvNCw0YLRh9C40YLRgdGPINGC0L7Qu9GM0LrQviDQu9C40YLQtdGA0LDQuyAwLgogICAgLy8gaGFzaCgxLCAiYWJjZGVmIiwgMHgwMCk7CgogICAgLy8g0J3QuNGA0LDQsdC+0YLQsNC10YI6INC+0LPRgNCw0L3QuNGH0LXQvdC40Y8g0L3QsCDRgdC60LvQtdC50LrRgyDRgtC+0LrQtdC90L7Qsi4KICAgIC8vIGhhc2goMSwgZm9vLCArc3RybGVuKGZvbykpOwp9CgojdW5kZWYgaGFzaAoKLy8g0JLQsNGA0LjQsNC90YIgMjog0YHQvtCy0YDQtdC80LXQvdC90YvQuSwg0YXQuNC/0YHRgtC10YDRgdC60LjQuSAtINC/0L4g0LzQtdGA0LUg0YHQuNC7INC/0YDQvtCy0LXRgNGP0LXRgtGB0Y8g0YLQuNC/LgoKI2RlZmluZSBoYXNoKGEsIGIpIF9HZW5lcmljKChiKSwgXAogICAgY29uc3QgY2hhcltzaXplb2YoYildOiBoYXNoZnVuYyhhLCBiLCBzaXplb2YoYikgLSAxKSxcCiAgICAgICAgICBjaGFyW3NpemVvZihiKV06IGhhc2hmdW5jKGEsIGIsIHNpemVvZihiKSAtIDEpLFwKICAgIGRlZmF1bHQ6ICAgICAgICAgICAgICAgaGFzaGZ1bmMoYSwgYiwgc3RybGVuKGIpKSkKCnN0YXRpYyB2b2lkIHRlc3QyKHZvaWQpCnsKICAgIGNvbnN0IGNoYXIgKmZvbyA9ICJhYmNkZWYiOwogICAgY2hhciAqYmFyID0gImFiY2RlZiI7CiAgICBjaGFyIGJheltdID0gImFiY2RlZiI7CgogICAgaGFzaCgxLCBmb28pOyAgICAgIC8vIHN0cmxlbgogICAgaGFzaCgyLCBiYXIpOyAgICAgIC8vIHN0cmxlbgogICAgaGFzaCgzLCBiYXopOyAgICAgIC8vIHNpemVvZgogICAgaGFzaCg0LCAiYWJjZGVmIik7IC8vIHNpemVvZgp9CgppbnQgbWFpbih2b2lkKQp7CiAgICB0ZXN0MSgpOwogICAgdGVzdDIoKTsKfQo=