#include <cstdio>
 
namespace intern {

  template<char... NN> struct string {

    static constexpr char const value[ sizeof...(NN) ]{NN...};

    static_assert( value[ sizeof...(NN) - 1 ] == '\0', "interned string was too long" );

    static constexpr auto data() { return value; }
  };

  template<char... N> constexpr char const string<N...>::value[];
 
  template<int N>
  constexpr char ch ( char const(&s)[N], int i ) { return i < N ? s[i] : '\0'; }

  template<typename T> struct is_string {
    static const bool value = false;
  };

  template<char... NN> struct is_string< string<NN...> > {
    static const bool value = true;
  };
}

//prefixing macros with a $ helps with readability
#define $c(a,b) intern::ch(a, b)

//10 characters + '\0', add $c(...) for more
#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)>


enum class op { plus, minus };
 
template<int R, int D, op O> struct doop {
	static const int value = O == op::plus ? R+D : R-D;
};
 
template<int R, int D, op O, char... N> struct parse;
 
template<int R, int D, op O, char C, char... N> struct parse<R, D, O, C, N...> {
	static const int value = parse<R, D*10+C-'0', O, N...>::value;
};
 
template<int R, int D, op O, char... N> struct parse<R, D, O, '+', N...> {
	static const int value = parse<doop<R,D,O>::value, 0, op::plus, N...>::value;
};
 
template<int R, int D, op O, char... N> struct parse<R, D, O, '-', N...> {
	static const int value = parse<doop<R,D,O>::value, 0, op::minus, N...>::value;
};
 
template<int R, int D, op O, char... N> struct parse<R, D, O, ' ', N...> {
	static const int value = parse<R, D, O, N...>::value;
};
 
template<int R, int D, op O, char... N> struct parse<R, D, O, '\0', N...> {
	static const int value = doop<R,D,O>::value;
};
 
template<typename T> struct calc;
template<char... N> struct calc< intern::string<N...> > {
	static const int value = parse<0, 0, op::plus, N...>::value;
};
 
#define calc_t(s) calc< $(s) >
 
int main() {
 
 	printf( "1. calc(100+20-10) = %d\n", calc_t("100+20-10")::value );

 	printf( "2. calc(100-180+50) = %d\n", calc_t("100-180+50")::value );
 
}
