fork download
  1. #include <string>
  2. #include <iostream>
  3. #include <utility>
  4. #include <type_traits>
  5.  
  6. template <char... c> struct literal
  7. {
  8. static constexpr char str[sizeof...( c ) + 1] = { c... };
  9. typedef literal type;
  10. };
  11. template <char... c>
  12. constexpr char literal<c...>::str[];
  13.  
  14. template <typename... s> struct concat
  15. : concat<typename s::type...> {};
  16. template <char... c1, char... c2, typename... s> struct concat<literal<c1...>,literal<c2...>, s...>
  17. : concat<literal<c1..., c2...>, s...> {};
  18. template <char... c> struct concat<literal<c...>>
  19. : literal<c...> {};
  20. template <> struct concat<>
  21. : literal<> {};
  22.  
  23. template <std::size_t N, typename L = literal<>> struct N_to_literal
  24. : N_to_literal<N / 10, concat<literal<('0' + N % 10)>,L>> {};
  25. template <typename L> struct N_to_literal<0, L>
  26. : L {};
  27. template <> struct N_to_literal<0, literal<>>
  28. : literal<'0'> {};
  29.  
  30. template <typename T> struct tag {};
  31.  
  32. template <typename T, typename U> struct map_pair
  33. {
  34. friend U lookup(tag<T>, map_pair);
  35. };
  36. literal<'u','n','k','n','o','w','n'> lookup(...);
  37.  
  38. template <typename... T> struct type_map : T... {};
  39.  
  40. typedef type_map<
  41. map_pair<void, literal<'v','o','i','d'>>,
  42. map_pair<char, literal<'c','h','a','r'>>,
  43. map_pair<signed char, literal<'s','i','g','n','e','d',' ','c','h','a','r'>>,
  44. map_pair<unsigned char, literal<'u','n','s','i','g','n','e','d',' ','c','h','a','r'>>,
  45. map_pair<short, literal<'s','h','o','r','t'>>,
  46. map_pair<unsigned short, literal<'u','n','s','i','g','n','e','d',' ','s','h','o','r','t'>>,
  47. map_pair<int, literal<'i','n','t'>>,
  48. map_pair<unsigned, literal<'u','n','s','i','g','n','e','d'>>,
  49. map_pair<long, literal<'l','o','n','g'>>,
  50. map_pair<unsigned long, literal<'u','n','s','i','g','n','e','d',' ','l','o','n','g'>>,
  51. map_pair<long long, literal<'l','o','n','g',' ','l','o','n','g'>>,
  52. map_pair<unsigned long long, literal<'u','n','s','i','g','n','e','d',' ','l','o','n','g',' ','l','o','n','g'>>,
  53. map_pair<wchar_t, literal<'w','c','h','a','r','_','t'>>,
  54. map_pair<char16_t, literal<'c','h','a','r','1','6','_','t'>>,
  55. map_pair<char32_t, literal<'c','h','a','r','3','2','_','t'>>,
  56. map_pair<float, literal<'f','l','o','a','t'>>,
  57. map_pair<double, literal<'d','o','u','b','l','e'>>,
  58. map_pair<long double, literal<'l','o','n','g',' ','d','o','u','b','l','e'>>,
  59. map_pair<std::nullptr_t, literal<':',':','s','t','d',':',':','n','u','l','l','p','t','r','_','t'>>> fundamental_types;
  60.  
  61. template <typename L, typename R, bool b> struct type_name_parts
  62. {
  63. typedef L left;
  64. typedef R right;
  65. static constexpr bool right_last = b;
  66. };
  67.  
  68. template <typename T, typename M> struct derive_name_parts;
  69.  
  70. template <typename T, typename M = fundamental_types> struct type_name
  71. : concat<typename derive_name_parts<T, M>::left, typename derive_name_parts<T, M>::right> {};
  72.  
  73. template <typename P, typename S> struct derive_left
  74. : type_name_parts<
  75. concat<typename P::left, std::conditional<P::right_last, literal<'('>, literal<>>, S>,
  76. concat<std::conditional<P::right_last, literal<')'>, literal<>>, typename P::right>,
  77. false> {};
  78.  
  79. template <typename P, typename S> struct derive_right
  80. : type_name_parts<typename P::left, concat<S, typename P::right>, true> {};
  81.  
  82. template <typename M, typename...> struct pretty_args;
  83. template <typename M> struct pretty_args<M>
  84. : literal<> {};
  85. template <typename M, typename T> struct pretty_args<M, T>
  86. : type_name<T, M> {};
  87. template <typename M, typename T, typename... Args> struct pretty_args<M, T, Args...>
  88. : concat<pretty_args<M, T>,literal<','>, pretty_args<M, Args...>> {};
  89.  
  90. template <typename T, typename M> struct derive_name_parts
  91. : type_name_parts<decltype(lookup(std::declval<tag<T>>(),std::declval<M>())), literal<>, false> {};
  92.  
  93. template <typename T, typename M> struct derive_name_parts<const T, M>
  94. : derive_left<derive_name_parts<T, M>, literal<' ','c','o','n','s','t'>> {};
  95. template <typename T, typename M> struct derive_name_parts<volatile T, M>
  96. : derive_left<derive_name_parts<T, M>, literal<' ','v','o','l','a','t','i','l','e'>> {};
  97. template <typename T, typename M> struct derive_name_parts<const volatile T, M>
  98. : derive_left<derive_name_parts<T, M>, literal<' ','c','o','n','s','t',' ','v','o','l','a','t','i','l','e'>> {};
  99. template <typename T, typename M> struct derive_name_parts<T*, M>
  100. : derive_left<derive_name_parts<T, M>, literal<'*'>> {};
  101. template <typename T, typename M> struct derive_name_parts<T&, M>
  102. : derive_left<derive_name_parts<T, M>, literal<'&'>> {};
  103. template <typename T, typename M> struct derive_name_parts<T&&, M>
  104. : derive_left<derive_name_parts<T, M>, literal<'&','&'>> {};
  105. template <typename T, typename M, std::size_t N> struct derive_name_parts<T[N], M>
  106. : derive_right<derive_name_parts<T, M>, concat<literal<'['>,N_to_literal<N>,literal<']'>>> {};
  107. template <typename T, typename M> struct derive_name_parts<T[], M>
  108. : derive_right<derive_name_parts<T, M>, literal<'[',']'>> {};
  109. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...), M>
  110. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')'>>> {};
  111. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const, M>
  112. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t'>>> {};
  113. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) volatile, M>
  114. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','v','o','l','a','t','i','l','e'>>> {};
  115. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const volatile, M>
  116. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t',' ','v','o','l','a','t','i','l','e'>>> {};
  117. #ifdef NO_BROKEN_REF_QUALIFIER
  118. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) &, M>
  119. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','&'>>> {};
  120. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const &, M>
  121. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t','&'>>> {};
  122. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) volatile &, M>
  123. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','v','o','l','a','t','i','l','e','&'>>> {};
  124. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const volatile &, M>
  125. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t',' ','v','o','l','a','t','i','l','e','&'>>> {};
  126. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) &&, M>
  127. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','&','&'>>> {};
  128. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const &&, M>
  129. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t','&','&'>>> {};
  130. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) volatile &&, M>
  131. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','v','o','l','a','t','i','l','e','&','&'>>> {};
  132. template <typename T, typename M, typename... Args> struct derive_name_parts<T(Args...) const volatile &&, M>
  133. : derive_right<derive_name_parts<T, M>, concat<literal<'('>, pretty_args<M, Args...>, literal<')','c','o','n','s','t',' ','v','o','l','a','t','i','l','e','&','&'>>> {};
  134. #endif
  135. template <typename T, typename M, typename C> struct derive_name_parts<T C::*, M>
  136. : derive_left<derive_name_parts<T, M>, concat<std::conditional<derive_name_parts<T, M>::right_last,literal<>,literal<' '>>, type_name<C, M>, literal<':',':','*'>>> {};
  137.  
  138. int main()
  139. {
  140. struct Foo;
  141. std::cout << type_name<int>::type::str << '\n';
  142. std::cout << type_name<int const>::type::str << '\n';
  143. std::cout << type_name<int*>::type::str << '\n';
  144. std::cout << type_name<int&&>::type::str << '\n';
  145. std::cout << type_name<int[]>::type::str << '\n';
  146. std::cout << type_name<int(void)>::type::str << '\n';
  147. std::cout << type_name<int(*)[12345]>::type::str << '\n';
  148. std::cout << type_name<void(int)>::type::str << '\n';
  149. std::cout << type_name<int&(int*, char)>::type::str << '\n';
  150. std::cout << type_name<int&(int*, char, int&(*&)(long,long long))>::type::str << '\n';
  151. std::cout << type_name<Foo>::type::str << '\n';
  152. std::cout << type_name<int Foo::*>::type::str << '\n';
  153. std::cout << type_name<int (Foo::*)()>::type::str << '\n';
  154. std::cout << type_name<int (Foo::*)(int, char)const volatile>::type::str << '\n';
  155.  
  156. typedef type_map<
  157. fundamental_types,
  158. map_pair<Foo, literal<'F','o','o'>>,
  159. map_pair<std::string, literal<':',':','s','t','d',':',':','s','t','r','i','n','g'>>> more_types;
  160. std::cout << type_name<Foo, more_types>::type::str << '\n';
  161. std::cout << type_name<int Foo::*, more_types>::type::str << '\n';
  162. std::cout << type_name<int (Foo::*)(), more_types>::type::str << '\n';
  163. #ifdef NO_BROKEN_REF_QUALIFIER
  164. std::cout << type_name<int (Foo::*)()&, more_types>::type::str << '\n';
  165. #endif
  166. std::cout << type_name<std::string (Foo::*)(int, char)const volatile, more_types>::type::str << '\n';
  167. }
Success #stdin #stdout 0s 2896KB
stdin
Standard input is empty
stdout
int
int const
int*
int&&
int[]
int()
int(*)[12345]
void(int)
int&(int*,char)
int&(int*,char,int&(*&)(long,long long))
unknown
int unknown::*
int(unknown::*)()
int(unknown::*)(int,char)const volatile
Foo
int Foo::*
int(Foo::*)()
::std::string(Foo::*)(int,char)const volatile