fork(3) download
  1. #include<iostream>
  2. #include<cctype>
  3. #include<utility>
  4. #include<cstddef>
  5.  
  6. /*
  7.  * 1. Define types, based in std::integral_constant and std::integer_sequence, to store our data
  8.  * 2. map_types_over_integer_constants (to concat the individual char-integral_constants into one pack of chars
  9.  * 3. constexpr_strlen
  10.  * 4. the macro the defines the relevant lambda, and calls the above functions
  11.  */
  12.  
  13. template<char c>
  14. using Char = std::integral_constant<char,c>;
  15.  
  16. template<char... c>
  17. struct CharPack : std::integer_sequence<char, c...> {
  18. static constexpr const char value0[] = {c...,'\0'};
  19. template< template<char...> class Template>
  20. using apply = Template<c...>; // This is in order to 'extract' the chars later
  21. };
  22. template<char... c>
  23. constexpr const char CharPack<c...>:: value0[];
  24.  
  25. template<typename F, typename T>
  26. struct map_types_over_integer_constants;
  27. template<typename F, size_t... i>
  28. struct map_types_over_integer_constants<F, std::integer_sequence<size_t, i...> > {
  29. using type = CharPack< F::get()[i] ... >;
  30. };
  31. constexpr size_t constexpr_strlen(const char * s) {
  32. return (*s=='\0')?0:(1+constexpr_strlen(s+1));
  33. }
  34.  
  35. template<typename F>
  36. struct map_to_each_char_in_string {
  37. using seq1N = std:: make_index_sequence< constexpr_strlen(F::get()) >;
  38. using type = typename map_types_over_integer_constants<F, seq1N> :: type;
  39. };
  40.  
  41. #define COMPILE_LITERAL_STRING_TO_CHARPACK(t_name, str) \
  42.   struct t_name ## required_nested_one { \
  43.   constexpr static const char * get() { return str; } \
  44.   }; \
  45.   using t_name = map_to_each_char_in_string<t_name ## required_nested_one> :: type
  46.  
  47. /* The above lines could go in a header file, string_to_charpack.hpp or something */
  48.  
  49. using std:: cout;
  50. using std:: endl;
  51.  
  52. template <char... c>
  53. struct char_sequence_to_type;
  54. template <> struct char_sequence_to_type< 'i','n','t' > { using type = int; };
  55. template <> struct char_sequence_to_type< 'c','h','a','r' > { using type = char; };
  56. template <> struct char_sequence_to_type< 's','t','r','i','n','g' > { using type = std:: string; };
  57. template <char... c>
  58. using char_sequence_to_type_t = typename char_sequence_to_type<c...>::type;
  59.  
  60. int main() {
  61. COMPILE_LITERAL_STRING_TO_CHARPACK(compiled_hello, "hello world");
  62. std:: cout << compiled_hello :: value0 << std:: endl;
  63.  
  64. COMPILE_LITERAL_STRING_TO_CHARPACK(compiled_i, "int");
  65. COMPILE_LITERAL_STRING_TO_CHARPACK(compiled_c, "char");
  66. COMPILE_LITERAL_STRING_TO_CHARPACK(compiled_s, "string");
  67. static_assert(std::is_same< compiled_i::apply<char_sequence_to_type_t> ,int>::value, "int");
  68. static_assert(std::is_same< compiled_c::apply<char_sequence_to_type_t> ,char>::value, "char");
  69. static_assert(std::is_same< compiled_s::apply<char_sequence_to_type_t> ,std:: string>::value, "string");
  70. }
  71.  
Success #stdin #stdout 0s 3140KB
stdin
Standard input is empty
stdout
hello world