fork(1) download
  1.  
  2. #include "boost/preprocessor.hpp"
  3.  
  4.  
  5. #define XXX_PP_ARG_N( \
  6.   _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
  7.   _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
  8.   _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
  9.   _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
  10.   _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
  11.   _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
  12.   _61,_62,_63,N,...) N
  13.  
  14. #define XXX_PP_RSEQ_N() \
  15.   63,62,61,60, \
  16.   59,58,57,56,55,54,53,52,51,50, \
  17.   49,48,47,46,45,44,43,42,41,40, \
  18.   39,38,37,36,35,34,33,32,31,30, \
  19.   29,28,27,26,25,24,23,22,21,20, \
  20.   19,18,17,16,15,14,13,12,11,10, \
  21.   9,8,7,6,5,4,3,2,1,0
  22.  
  23. #define XXX_PP_NARG_(...) \
  24.   XXX_PP_ARG_N(__VA_ARGS__)
  25.  
  26. #define XXX_PP_NARG(...) \
  27.   XXX_PP_NARG_(__VA_ARGS__,XXX_PP_RSEQ_N())
  28.  
  29. #define XXX_TUPLE_SIZE_INTERNAL(TUPLE) XXX_PP_NARG TUPLE
  30.  
  31. #define XXX_TUPLE_CHOICE(i) \
  32. BOOST_PP_APPLY( \
  33. BOOST_PP_TUPLE_ELEM( \
  34. 25, i, (\
  35. (0), (1), (2), (3) , (4) , (5) , (6) , (7) , (8) , (9) , (10) , (11) \
  36. , (12) , (13) , (14) , (15) , (16) , (17) , (18) , (19) , (20) , (21) \
  37. , (22) , (23) , (24) \
  38.  ) \
  39. ) \
  40. )
  41.  
  42.  
  43. #define BOOST_PP_BOOL_00 BOOST_PP_BOOL_0
  44. #define BOOST_PP_BOOL_01 BOOST_PP_BOOL_1
  45. #define BOOST_PP_BOOL_02 BOOST_PP_BOOL_2
  46. #define BOOST_PP_BOOL_03 BOOST_PP_BOOL_3
  47. #define BOOST_PP_BOOL_04 BOOST_PP_BOOL_4
  48. #define BOOST_PP_BOOL_05 BOOST_PP_BOOL_5
  49. #define BOOST_PP_BOOL_06 BOOST_PP_BOOL_6
  50. #define BOOST_PP_BOOL_07 BOOST_PP_BOOL_7
  51. #define BOOST_PP_BOOL_08 BOOST_PP_BOOL_8
  52. #define BOOST_PP_BOOL_09 BOOST_PP_BOOL_9
  53. #define BOOST_PP_BOOL_010 BOOST_PP_BOOL_10
  54. #define BOOST_PP_BOOL_011 BOOST_PP_BOOL_11
  55. #define BOOST_PP_BOOL_012 BOOST_PP_BOOL_12
  56. #define BOOST_PP_BOOL_013 BOOST_PP_BOOL_13
  57. #define BOOST_PP_BOOL_014 BOOST_PP_BOOL_14
  58. #define BOOST_PP_BOOL_015 BOOST_PP_BOOL_15
  59. #define BOOST_PP_BOOL_016 BOOST_PP_BOOL_16
  60. #define BOOST_PP_BOOL_017 BOOST_PP_BOOL_17
  61. #define BOOST_PP_BOOL_018 BOOST_PP_BOOL_18
  62. #define BOOST_PP_BOOL_019 BOOST_PP_BOOL_19
  63. #define BOOST_PP_BOOL_020 BOOST_PP_BOOL_20
  64. #define BOOST_PP_BOOL_021 BOOST_PP_BOOL_21
  65. #define BOOST_PP_BOOL_022 BOOST_PP_BOOL_22
  66. #define BOOST_PP_BOOL_023 BOOST_PP_BOOL_23
  67. #define BOOST_PP_BOOL_024 BOOST_PP_BOOL_24
  68. #define BOOST_PP_BOOL_025 BOOST_PP_BOOL_25
  69. #define BOOST_PP_BOOL_026 BOOST_PP_BOOL_26
  70. #define BOOST_PP_BOOL_027 BOOST_PP_BOOL_27
  71. #define BOOST_PP_BOOL_028 BOOST_PP_BOOL_28
  72. #define BOOST_PP_BOOL_029 BOOST_PP_BOOL_29
  73. #define BOOST_PP_BOOL_030 BOOST_PP_BOOL_30
  74. #define BOOST_PP_BOOL_031 BOOST_PP_BOOL_31
  75. #define BOOST_PP_BOOL_032 BOOST_PP_BOOL_32
  76. #define BOOST_PP_BOOL_033 BOOST_PP_BOOL_33
  77. #define BOOST_PP_BOOL_034 BOOST_PP_BOOL_34
  78. #define BOOST_PP_BOOL_035 BOOST_PP_BOOL_35
  79. #define BOOST_PP_BOOL_036 BOOST_PP_BOOL_36
  80. #define BOOST_PP_BOOL_037 BOOST_PP_BOOL_37
  81. #define BOOST_PP_BOOL_038 BOOST_PP_BOOL_38
  82. #define BOOST_PP_BOOL_039 BOOST_PP_BOOL_39
  83. #define BOOST_PP_BOOL_040 BOOST_PP_BOOL_40
  84. #define BOOST_PP_BOOL_041 BOOST_PP_BOOL_41
  85. #define BOOST_PP_BOOL_042 BOOST_PP_BOOL_42
  86. #define BOOST_PP_BOOL_043 BOOST_PP_BOOL_43
  87. #define BOOST_PP_BOOL_044 BOOST_PP_BOOL_44
  88. #define BOOST_PP_BOOL_045 BOOST_PP_BOOL_45
  89. #define BOOST_PP_BOOL_046 BOOST_PP_BOOL_46
  90. #define BOOST_PP_BOOL_047 BOOST_PP_BOOL_47
  91. #define BOOST_PP_BOOL_048 BOOST_PP_BOOL_48
  92. #define BOOST_PP_BOOL_049 BOOST_PP_BOOL_49
  93. #define BOOST_PP_BOOL_050 BOOST_PP_BOOL_50
  94. #define BOOST_PP_BOOL_051 BOOST_PP_BOOL_51
  95. #define BOOST_PP_BOOL_052 BOOST_PP_BOOL_52
  96. #define BOOST_PP_BOOL_053 BOOST_PP_BOOL_53
  97. #define BOOST_PP_BOOL_054 BOOST_PP_BOOL_54
  98. #define BOOST_PP_BOOL_055 BOOST_PP_BOOL_55
  99. #define BOOST_PP_BOOL_056 BOOST_PP_BOOL_56
  100. #define BOOST_PP_BOOL_057 BOOST_PP_BOOL_57
  101. #define BOOST_PP_BOOL_058 BOOST_PP_BOOL_58
  102. #define BOOST_PP_BOOL_059 BOOST_PP_BOOL_59
  103. #define BOOST_PP_BOOL_060 BOOST_PP_BOOL_60
  104. #define BOOST_PP_BOOL_061 BOOST_PP_BOOL_61
  105. #define BOOST_PP_BOOL_062 BOOST_PP_BOOL_62
  106. #define BOOST_PP_BOOL_063 BOOST_PP_BOOL_63
  107.  
  108.  
  109. #define BOOST_PP_DEC_00 BOOST_PP_DEC_0
  110. #define BOOST_PP_DEC_01 BOOST_PP_DEC_1
  111. #define BOOST_PP_DEC_02 BOOST_PP_DEC_2
  112. #define BOOST_PP_DEC_03 BOOST_PP_DEC_3
  113. #define BOOST_PP_DEC_04 BOOST_PP_DEC_4
  114. #define BOOST_PP_DEC_05 BOOST_PP_DEC_5
  115. #define BOOST_PP_DEC_06 BOOST_PP_DEC_6
  116. #define BOOST_PP_DEC_07 BOOST_PP_DEC_7
  117. #define BOOST_PP_DEC_08 BOOST_PP_DEC_8
  118. #define BOOST_PP_DEC_09 BOOST_PP_DEC_9
  119. #define BOOST_PP_DEC_010 BOOST_PP_DEC_10
  120. #define BOOST_PP_DEC_011 BOOST_PP_DEC_11
  121. #define BOOST_PP_DEC_012 BOOST_PP_DEC_12
  122. #define BOOST_PP_DEC_013 BOOST_PP_DEC_13
  123. #define BOOST_PP_DEC_014 BOOST_PP_DEC_14
  124. #define BOOST_PP_DEC_015 BOOST_PP_DEC_15
  125. #define BOOST_PP_DEC_016 BOOST_PP_DEC_16
  126. #define BOOST_PP_DEC_017 BOOST_PP_DEC_17
  127. #define BOOST_PP_DEC_018 BOOST_PP_DEC_18
  128. #define BOOST_PP_DEC_019 BOOST_PP_DEC_19
  129. #define BOOST_PP_DEC_020 BOOST_PP_DEC_20
  130. #define BOOST_PP_DEC_021 BOOST_PP_DEC_21
  131. #define BOOST_PP_DEC_022 BOOST_PP_DEC_22
  132. #define BOOST_PP_DEC_023 BOOST_PP_DEC_23
  133. #define BOOST_PP_DEC_024 BOOST_PP_DEC_24
  134. #define BOOST_PP_DEC_025 BOOST_PP_DEC_25
  135. #define BOOST_PP_DEC_026 BOOST_PP_DEC_26
  136. #define BOOST_PP_DEC_027 BOOST_PP_DEC_27
  137. #define BOOST_PP_DEC_028 BOOST_PP_DEC_28
  138. #define BOOST_PP_DEC_029 BOOST_PP_DEC_29
  139. #define BOOST_PP_DEC_030 BOOST_PP_DEC_30
  140. #define BOOST_PP_DEC_031 BOOST_PP_DEC_31
  141. #define BOOST_PP_DEC_032 BOOST_PP_DEC_32
  142. #define BOOST_PP_DEC_033 BOOST_PP_DEC_33
  143. #define BOOST_PP_DEC_034 BOOST_PP_DEC_34
  144. #define BOOST_PP_DEC_035 BOOST_PP_DEC_35
  145. #define BOOST_PP_DEC_036 BOOST_PP_DEC_36
  146. #define BOOST_PP_DEC_037 BOOST_PP_DEC_37
  147. #define BOOST_PP_DEC_038 BOOST_PP_DEC_38
  148. #define BOOST_PP_DEC_039 BOOST_PP_DEC_39
  149. #define BOOST_PP_DEC_040 BOOST_PP_DEC_40
  150. #define BOOST_PP_DEC_041 BOOST_PP_DEC_41
  151. #define BOOST_PP_DEC_042 BOOST_PP_DEC_42
  152. #define BOOST_PP_DEC_043 BOOST_PP_DEC_43
  153. #define BOOST_PP_DEC_044 BOOST_PP_DEC_44
  154. #define BOOST_PP_DEC_045 BOOST_PP_DEC_45
  155. #define BOOST_PP_DEC_046 BOOST_PP_DEC_46
  156. #define BOOST_PP_DEC_047 BOOST_PP_DEC_47
  157. #define BOOST_PP_DEC_048 BOOST_PP_DEC_48
  158. #define BOOST_PP_DEC_049 BOOST_PP_DEC_49
  159. #define BOOST_PP_DEC_050 BOOST_PP_DEC_50
  160. #define BOOST_PP_DEC_051 BOOST_PP_DEC_51
  161. #define BOOST_PP_DEC_052 BOOST_PP_DEC_52
  162. #define BOOST_PP_DEC_053 BOOST_PP_DEC_53
  163. #define BOOST_PP_DEC_054 BOOST_PP_DEC_54
  164. #define BOOST_PP_DEC_055 BOOST_PP_DEC_55
  165. #define BOOST_PP_DEC_056 BOOST_PP_DEC_56
  166. #define BOOST_PP_DEC_057 BOOST_PP_DEC_57
  167. #define BOOST_PP_DEC_058 BOOST_PP_DEC_58
  168. #define BOOST_PP_DEC_059 BOOST_PP_DEC_59
  169. #define BOOST_PP_DEC_060 BOOST_PP_DEC_60
  170. #define BOOST_PP_DEC_061 BOOST_PP_DEC_61
  171. #define BOOST_PP_DEC_062 BOOST_PP_DEC_62
  172. #define BOOST_PP_DEC_063 BOOST_PP_DEC_63
  173.  
  174.  
  175. #define XXX_TO_NUMx(x) 0 ## x
  176. #define XXX_TO_NUM(x) BOOST_PP_ADD(0,XXX_TO_NUMx(x))
  177.  
  178.  
  179. #define XXX_STRINGIZEX(x) # x
  180. #define XXX_VSTRINGIZE_SINGLE(a,b,x) XXX_STRINGIZE(x)
  181. #define XXX_VSTRINGIZE_TUPLE(tpl) XXX_TUPLE_FOR_EACH(XXX_VSTRINGIZE_SINGLE,,tpl)
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188. #define XXX_TUPLE_SIZE(TUPLE) XXX_TO_NUM(XXX_TUPLE_CHOICE(XXX_TUPLE_SIZE_INTERNAL(TUPLE)))
  189.  
  190.  
  191.  
  192.  
  193. #define XXX_TUPLE_FOR_EACH(MACRO,DATA,TUPLE) BOOST_PP_LIST_FOR_EACH(MACRO,DATA,BOOST_PP_TUPLE_TO_LIST(XXX_TUPLE_SIZE(TUPLE),TUPLE))
  194.  
  195. #define XXX_STRINGIZE(x) XXX_STRINGIZEX(x)
  196.  
  197. #define XXX_VSTRINGIZE(...) XXX_VSTRINGIZE_TUPLE((__VA_ARGS__))
  198.  
  199. #define XXX_CAST_TO_VOID_ELEMENT(r,data,elem) (void)(elem);
  200. #define XXX_CAST_TO_VOID_INTERNAL(TUPLE) \
  201. XXX_TUPLE_FOR_EACH(XXX_CAST_TO_VOID_ELEMENT,,TUPLE)
  202.  
  203. #define XXX_CAST_TO_VOID(...) XXX_CAST_TO_VOID_INTERNAL((__VA_ARGS__))
  204.  
  205.  
  206.  
  207. #define XXX_ENUM_EXTRACT_SP(en) BOOST_PP_TUPLE_ELEM(XXX_TUPLE_SIZE(en),0,en) = BOOST_PP_TUPLE_ELEM(XXX_TUPLE_SIZE(en),1,en)
  208. #define XXX_ENUM_ELEMENT(r,data,elem) BOOST_PP_IF( XXX_TUPLE_SIZE(elem), XXX_ENUM_EXTRACT_SP(elem), elem) ,
  209. #define XXX_ENUM_EXTRACT_ELEMENT(en) BOOST_PP_TUPLE_ELEM(XXX_TUPLE_SIZE(en),0,en)
  210. #define XXX_ENUM_CASE_ELEMENT(en) BOOST_PP_IF( XXX_TUPLE_SIZE(en), XXX_ENUM_EXTRACT_ELEMENT(en), en )
  211.  
  212. #define XXX_ENUM_CASE(r,data,elem) case data :: XXX_ENUM_CASE_ELEMENT(elem) : return #data "::" XXX_STRINGIZE(XXX_ENUM_CASE_ELEMENT(elem));
  213.  
  214. #define XXX_ENUM_IFELSE(r,data,elem) else if( en == data :: XXX_ENUM_CASE_ELEMENT(elem)) { return #data "::" XXX_STRINGIZE(XXX_ENUM_CASE_ELEMENT(elem)); }
  215. #define XXX_ENUM_CASTLIST(r,data,elem) { XXX_STRINGIZE(XXX_ENUM_CASE_ELEMENT(elem)), data :: XXX_ENUM_CASE_ELEMENT(elem) },
  216. #define XXX_ENUM_QUALIFIED_CASTLIST(r,data,elem) { #data "::" XXX_STRINGIZE(XXX_ENUM_CASE_ELEMENT(elem)), data :: XXX_ENUM_CASE_ELEMENT(elem) },
  217.  
  218. #define XXX_ENUM_INTERNAL(TYPE,NAME,TUPLE) \
  219. enum TYPE \
  220. { \
  221. XXX_TUPLE_FOR_EACH(XXX_ENUM_ELEMENT,,TUPLE) \
  222. BOOST_PP_CAT(last_enum_,NAME) \
  223. }; \
  224. \
  225. inline \
  226. const char* to_string( NAME en ) \
  227. { \
  228. if(false) \
  229. { \
  230. } \
  231. XXX_TUPLE_FOR_EACH(XXX_ENUM_IFELSE,NAME,TUPLE) \
  232. else if( en == NAME :: BOOST_PP_CAT(last_enum_,NAME) ) \
  233. { \
  234. return XXX_VSTRINGIZE(NAME,::, BOOST_PP_CAT(last_enum_,NAME)); \
  235. } \
  236. else \
  237. { \
  238. return "Invalid enum value specified for " # NAME; \
  239. } \
  240. } \
  241. \
  242. inline \
  243. std::ostream& operator<<( std::ostream& os, const NAME& en ) \
  244. { \
  245. os << to_string(en); \
  246. return os; \
  247. } \
  248. \
  249. \
  250. inline \
  251. NAME do_enum_cast( const std::string& s, const ::xxx::enum_cast_adl_helper<NAME>& ) \
  252. { \
  253. static const std::unordered_map<std::string,NAME> map = \
  254. { \
  255. XXX_TUPLE_FOR_EACH(XXX_ENUM_CASTLIST,NAME,TUPLE) \
  256. XXX_TUPLE_FOR_EACH(XXX_ENUM_QUALIFIED_CASTLIST,NAME,TUPLE) \
  257. }; \
  258. \
  259. auto cit = map.find(s); \
  260. if( cit == map.end() ) \
  261. { \
  262. /*XXX_THROW(xxx::exception,"Invalid value '%1%' to cast to enum " #NAME ,s);*/ \
  263. throw std::runtime_error("Invalid value to cast to enum"); \
  264. } \
  265. return cit->second; \
  266. }
  267.  
  268. #define XXX_ENUM(NAME,TUPLE) XXX_ENUM_INTERNAL(NAME,NAME,TUPLE)
  269. #define XXX_ENUM_CLASS(NAME,TUPLE) XXX_ENUM_INTERNAL(class NAME,NAME,TUPLE)
  270. #define XXX_ENUM_CLASS_TYPE(NAME,TYPE,TUPLE) XXX_ENUM_INTERNAL(class NAME : TYPE,NAME,TUPLE)
  271. #define XXX_ENUM_TYPE(NAME,TYPE,TUPLE) XXX_ENUM_INTERNAL(NAME : TYPE,NAME,TUPLE)
  272.  
  273.  
  274.  
  275.  
  276.  
  277. #include <iostream>
  278. #include <string>
  279. #include <unordered_map>
  280.  
  281. namespace xxx
  282. {
  283.  
  284. template<class T>
  285. struct enum_cast_adl_helper { };
  286.  
  287. template<class E>
  288. E enum_cast( const std::string& s )
  289. {
  290. return do_enum_cast(s,enum_cast_adl_helper<E>());
  291. }
  292.  
  293. template<class E>
  294. E enum_cast( const char* cs )
  295. {
  296. std::string s(cs);
  297. return enum_cast<E>(s);
  298. }
  299.  
  300. } // namespace xxx
  301.  
  302.  
  303. XXX_ENUM(foo,(a,b,(c,42)));
  304.  
  305. int main(int argc, const char *argv[])
  306. {
  307. std::cout << "foo::a = " << foo::a << "\n";
  308. std::cout << "(int)foo::c = " << (int)foo::c << "\n";
  309. std::cout << "to_string(foo::b) = " << to_string(foo::b) << "\n";
  310.  
  311.  
  312. std::cout << "xxx::enum_cast<foo>(\"b\") = " << xxx::enum_cast<foo>("b") << "\n";
  313. }
  314.  
  315. // vim: tabstop=4 shiftwidth=4 noexpandtab
Success #stdin #stdout 0s 3276KB
stdin
Standard input is empty
stdout
foo::a = foo::a
(int)foo::c = 42
to_string(foo::b) = foo::b
xxx::enum_cast<foo>("b") = foo::b