fork(1) download
  1. #include <cstdio>
  2.  
  3. namespace intern {
  4.  
  5. template<char... NN> struct string {
  6.  
  7. static constexpr char const value[ sizeof...(NN) ]{NN...};
  8.  
  9. static_assert( value[ sizeof...(NN) - 1 ] == '\0', "interned string was too long" );
  10.  
  11. static constexpr auto data() { return value; }
  12. };
  13.  
  14. template<char... N> constexpr char const string<N...>::value[];
  15.  
  16. template<int N>
  17. constexpr char ch ( char const(&s)[N], int i ) { return i < N ? s[i] : '\0'; }
  18.  
  19. template<typename T> struct is_string {
  20. static const bool value = false;
  21. };
  22.  
  23. template<char... NN> struct is_string< string<NN...> > {
  24. static const bool value = true;
  25. };
  26. }
  27.  
  28. //prefixing macros with a $ helps with readability
  29. #define $c(a,b) intern::ch(a, b)
  30.  
  31. //10 characters + '\0', add $c(...) for more
  32. #define $(s) intern::string<$c(s,0),$c(s,1),$c(s,2),$c(s,3),$c(s,4),$c(s,5),$c(s,6),$c(s,7),$c(s,8),$c(s,9),$c(s,10)>
  33.  
  34.  
  35. enum class op { plus, minus };
  36.  
  37. template<int R, int D, op O> struct doop {
  38. static const int value = O == op::plus ? R+D : R-D;
  39. };
  40.  
  41. template<int R, int D, op O, char... N> struct parse;
  42.  
  43. template<int R, int D, op O, char C, char... N> struct parse<R, D, O, C, N...> {
  44. static const int value = parse<R, D*10+C-'0', O, N...>::value;
  45. };
  46.  
  47. template<int R, int D, op O, char... N> struct parse<R, D, O, '+', N...> {
  48. static const int value = parse<doop<R,D,O>::value, 0, op::plus, N...>::value;
  49. };
  50.  
  51. template<int R, int D, op O, char... N> struct parse<R, D, O, '-', N...> {
  52. static const int value = parse<doop<R,D,O>::value, 0, op::minus, N...>::value;
  53. };
  54.  
  55. template<int R, int D, op O, char... N> struct parse<R, D, O, ' ', N...> {
  56. static const int value = parse<R, D, O, N...>::value;
  57. };
  58.  
  59. template<int R, int D, op O, char... N> struct parse<R, D, O, '\0', N...> {
  60. static const int value = doop<R,D,O>::value;
  61. };
  62.  
  63. template<typename T> struct calc;
  64. template<char... N> struct calc< intern::string<N...> > {
  65. static const int value = parse<0, 0, op::plus, N...>::value;
  66. };
  67.  
  68. #define calc_t(s) calc< $(s) >
  69.  
  70. int main() {
  71.  
  72. printf( "1. calc(100+20-10) = %d\n", calc_t("100+20-10")::value );
  73.  
  74. printf( "2. calc(100-180+50) = %d\n", calc_t("100-180+50")::value );
  75.  
  76. }
  77.  
Success #stdin #stdout 0s 15224KB
stdin
Standard input is empty
stdout
1. calc(100+20-10) = 110
2. calc(100-180+50) = -30