SilverTES

C++ Macro hack to create auto increment unique ID constant

Sep 5th, 2017
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.80 KB | None | 0 0
  1. //----------------------------------------------------------- C++98 METHOD
  2.  
  3. #include <stdlib.h>
  4.  
  5. template< size_t n > // This type returns a number through function lookup.
  6. struct cn // The function returns cn<n>.
  7.     { char data[ n + 1 ]; }; // The caller uses (sizeof fn() - 1).
  8.  
  9. template< typename id, size_t n, size_t acc >
  10. cn< acc > seen( id, cn< n >, cn< acc > ); // Default fallback case.
  11.  
  12. /* Evaluate the counter by finding the last defined overload.
  13.    Each function, when defined, alters the lookup sequence for lower-order
  14.    functions. */
  15. #define counter_read( id ) \
  16. ( sizeof seen( id(), cn< 1 >(), cn< \
  17. ( sizeof seen( id(), cn< 2 >(), cn< \
  18. ( sizeof seen( id(), cn< 4 >(), cn< \
  19. ( sizeof seen( id(), cn< 8 >(), cn< \
  20. ( sizeof seen( id(), cn< 16 >(), cn< \
  21. ( sizeof seen( id(), cn< 32 >(), cn< 0 \
  22. /* Add more as desired; trimmed for Stack Overflow code block. */ \
  23.                       >() ).data - 1 ) \
  24.                       >() ).data - 1 ) \
  25.                       >() ).data - 1 ) \
  26.                       >() ).data - 1 ) \
  27.                       >() ).data - 1 ) \
  28.                       >() ).data - 1 )
  29.  
  30. /* Define a single new function with place-value equal to the bit flipped to 1
  31.    by the increment operation.
  32.    This is the lowest-magnitude function yet undefined in the current context
  33.    of defined higher-magnitude functions. */
  34. #define counter_inc( id ) \
  35. cn< counter_read( id ) + 1 > \
  36. seen( id, cn< ( counter_read( id ) + 1 ) & ~ counter_read( id ) >, \
  37.           cn< ( counter_read( id ) + 1 ) & counter_read( id ) > )
  38.  
  39. struct my_cnt {};
  40.  
  41. int const a = counter_read( my_cnt );
  42. counter_inc( my_cnt );
  43. counter_inc( my_cnt );
  44. counter_inc( my_cnt );
  45. counter_inc( my_cnt );
  46. counter_inc( my_cnt );
  47.  
  48. int const b = counter_read( my_cnt );
  49.  
  50. counter_inc( my_cnt );
  51.  
  52. #include <iostream>
  53.  
  54. int main() {
  55.     std::cout << a << ' ' << b << '\n';
  56.  
  57.     std::cout << counter_read( my_cnt ) << '\n';
  58. }
  59.  
  60. //----------------------------------------------------------- C++11 METHOD
  61.  
  62. #define COUNTER_READ_CRUMB( TAG, RANK, ACC ) counter_crumb( TAG(), constant_index< RANK >(), constant_index< ACC >() )
  63. #define COUNTER_READ( TAG ) COUNTER_READ_CRUMB( TAG, 1, COUNTER_READ_CRUMB( TAG, 2, COUNTER_READ_CRUMB( TAG, 4, COUNTER_READ_CRUMB( TAG, 8, \
  64.     COUNTER_READ_CRUMB( TAG, 16, COUNTER_READ_CRUMB( TAG, 32, COUNTER_READ_CRUMB( TAG, 64, COUNTER_READ_CRUMB( TAG, 128, 0 ) ) ) ) ) ) ) )
  65.  
  66. #define COUNTER_INC( TAG ) \
  67. constant_index< COUNTER_READ( TAG ) + 1 > \
  68. constexpr counter_crumb( TAG, constant_index< ( COUNTER_READ( TAG ) + 1 ) & ~ COUNTER_READ( TAG ) >, \
  69.                             constant_index< ( COUNTER_READ( TAG ) + 1 ) & COUNTER_READ( TAG ) > ) { return {}; }
  70.  
  71. #define COUNTER_LINK_NAMESPACE( NS ) using NS::counter_crumb;
  72.  
  73. #include <utility>
  74.  
  75. template< std::size_t n >
  76. struct constant_index : std::integral_constant< std::size_t, n > {};
  77.  
  78. template< typename id, std::size_t rank, std::size_t acc >
  79. constexpr constant_index< acc > counter_crumb( id, constant_index< rank >, constant_index< acc > ) { return {}; } // found by ADL via constant_index
  80.  
  81. // define your different counter here
  82. struct my_cnt {};
  83. struct my_cnt2 {};
  84.  
  85.  
  86. #include <iostream>
  87.  
  88. //COUNTER_INC( my_cnt ); // increment counter !
  89. struct A
  90. {
  91.     static int constexpr type = COUNTER_READ(my_cnt); // read counter value !
  92. };
  93.  
  94. COUNTER_INC( my_cnt );
  95. struct B
  96. {
  97.     static int constexpr type = COUNTER_READ(my_cnt);
  98. };
  99.  
  100. COUNTER_INC( my_cnt );
  101. struct C
  102. {
  103.     static int constexpr type = COUNTER_READ(my_cnt);
  104. };
  105.  
  106. COUNTER_INC( my_cnt );
  107. struct D
  108. {
  109.     static int constexpr type = COUNTER_READ(my_cnt2);
  110. };
  111.  
  112. int main() {
  113.  
  114.     std::cout << "A::type = "<< A::type << '\n';
  115.     std::cout << "B::type = "<< B::type << '\n';
  116.     std::cout << "C::type = "<< C::type << '\n';
  117.     std::cout << "D::type = "<< D::type << '\n';
  118. }
Add Comment
Please, Sign In to add comment