fork(1) download
  1. #include <iostream>
  2. #include <cstdint>
  3. #include <string>
  4.  
  5. // Sequence of char
  6. template <char...Cs> struct char_sequence
  7. {
  8. template <char C> using push_back = char_sequence<Cs..., C>;
  9. };
  10.  
  11. // Remove all chars from char_sequence from '\0'
  12. template <typename, char...> struct strip_sequence;
  13.  
  14. template <char...Cs>
  15. struct strip_sequence<char_sequence<>, Cs...>
  16. {
  17. using type = char_sequence<Cs...>;
  18. };
  19.  
  20. template <char...Cs, char...Cs2>
  21. struct strip_sequence<char_sequence<'\0', Cs...>, Cs2...>
  22. {
  23. using type = char_sequence<Cs2...>;
  24. };
  25.  
  26. template <char...Cs, char C, char...Cs2>
  27. struct strip_sequence<char_sequence<C, Cs...>, Cs2...>
  28. {
  29. using type = typename strip_sequence<char_sequence<Cs...>, Cs2..., C>::type;
  30. };
  31.  
  32. // struct to create a aligned char array
  33. template <typename chars> struct static_string;
  34.  
  35. template <char...Cs>
  36. struct static_string<char_sequence<Cs...>>
  37. {
  38. static const std::string str;
  39. };
  40.  
  41. template <char...Cs>
  42. const
  43. std::string static_string<char_sequence<Cs...>>::str = {Cs...};
  44.  
  45. // helper to get the i_th character (`\0` for out of bound)
  46. template <std::size_t I, std::size_t N>
  47. constexpr char at(const char (&a)[N]) { return I < N ? a[I] : '\0'; }
  48.  
  49. // helper to check if the c-string will not be truncated
  50. template <std::size_t max_size, std::size_t N>
  51. constexpr bool check_size(const char (&)[N])
  52. {
  53. static_assert(N <= max_size, "string too long");
  54. return N <= max_size;
  55. }
  56.  
  57. // Helper macros to build char_sequence from c-string
  58. #define PUSH_BACK_8(S, I) \
  59.   ::push_back<at<(I) + 0>(S)>::push_back<at<(I) + 1>(S)> \
  60.   ::push_back<at<(I) + 2>(S)>::push_back<at<(I) + 3>(S)> \
  61.   ::push_back<at<(I) + 4>(S)>::push_back<at<(I) + 5>(S)> \
  62.   ::push_back<at<(I) + 6>(S)>::push_back<at<(I) + 7>(S)>
  63.  
  64. #define PUSH_BACK_32(S, I) \
  65.   PUSH_BACK_8(S, (I) + 0) PUSH_BACK_8(S, (I) + 8) \
  66.   PUSH_BACK_8(S, (I) + 16) PUSH_BACK_8(S, (I) + 24)
  67.  
  68. #define PUSH_BACK_128(S, I) \
  69.   PUSH_BACK_32(S, (I) + 0) PUSH_BACK_32(S, (I) + 32) \
  70.   PUSH_BACK_32(S, (I) + 64) PUSH_BACK_32(S, (I) + 96)
  71.  
  72. // Macro to create char_sequence from c-string (limited to 128 chars)
  73. #define MAKE_CHAR_SEQUENCE(S) \
  74.   strip_sequence<char_sequence<> \
  75.   PUSH_BACK_128(S, 0) \
  76.   ::push_back<check_size<128>(S) ? '\0' : '\0'> \
  77.   >::type
  78.  
  79. // Macro to return an static std::string
  80. #define STATIC_STRING(S) \
  81.   static_string<MAKE_CHAR_SEQUENCE(S)>::str
  82.  
  83. void foo(const std::string& s)
  84. {
  85. std::cout << s << " " << std::hex << static_cast<const void*>(&s) << std::endl;
  86. }
  87.  
  88. int main()
  89. {
  90. foo(STATIC_STRING("Static_string"));
  91. foo(STATIC_STRING("Bar"));
  92. foo(STATIC_STRING("Static_string"));
  93.  
  94. foo("c-string");
  95. foo("c-string_Bar");
  96. foo("c-string");
  97.  
  98. return 0;
  99. }
  100.  
Success #stdin #stdout 0s 3472KB
stdin
Standard input is empty
stdout
Static_string 0x8049224
Bar 0x8049220
Static_string 0x8049224
c-string 0xbfd0af6c
c-string_Bar 0xbfd0af6c
c-string 0xbfd0af6c