fork download
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. static int hashfunc(int a, const char *b, size_t length)
  5. {
  6. printf("hashfunc(%i, %.*s, %zu)\n", a, length, b, length);
  7. return 4;
  8. }
  9.  
  10. // Вариант 1: "Мааам, у меня паттерн-матчинг!".
  11.  
  12. #define cat_12_(x, ...) x ## __VA_ARGS__
  13. #define choose_2_(x, v, ...) v
  14. #define choose_(p, ...) choose_2_(__VA_ARGS__, p,)
  15. #define hash(a, b, c) hashfunc(a, b, choose_(c, cat_12_(hash_, c(b))))
  16. #define hash_0 , -1+sizeof
  17.  
  18. static void test1(void)
  19. {
  20. const char *foo = "abcdef";
  21. char *bar = "abcdef";
  22.  
  23. hash(1, foo, strlen(foo)); // strlen
  24. hash(2, bar, strlen(bar)); // strlen
  25. hash(3, "abcdef", 0); // sizeof
  26.  
  27. // Ниработает: матчится только литерал 0.
  28. // hash(1, "abcdef", 0x00);
  29.  
  30. // Ниработает: ограничения на склейку токенов.
  31. // hash(1, foo, +strlen(foo));
  32. }
  33.  
  34. #undef hash
  35.  
  36. // Вариант 2: современный, хипстерский - по мере сил проверяется тип.
  37.  
  38. #define hash(a, b) _Generic((b), \
  39.   const char[sizeof(b)]: hashfunc(a, b, sizeof(b) - 1),\
  40.   char[sizeof(b)]: hashfunc(a, b, sizeof(b) - 1),\
  41.   default: hashfunc(a, b, strlen(b)))
  42.  
  43. static void test2(void)
  44. {
  45. const char *foo = "abcdef";
  46. char *bar = "abcdef";
  47. char baz[] = "abcdef";
  48.  
  49. hash(1, foo); // strlen
  50. hash(2, bar); // strlen
  51. hash(3, baz); // sizeof
  52. hash(4, "abcdef"); // sizeof
  53. }
  54.  
  55. int main(void)
  56. {
  57. test1();
  58. test2();
  59. }
  60.  
Success #stdin #stdout 0s 2168KB
stdin
Standard input is empty
stdout
hashfunc(1, abcdef, 6)
hashfunc(2, abcdef, 6)
hashfunc(3, abcdef, 6)
hashfunc(1, abcdef, 6)
hashfunc(2, abcdef, 6)
hashfunc(3, abcdef, 6)
hashfunc(4, abcdef, 6)