fork download
  1. #include <iostream>
  2. #include <tuple>
  3. #include <functional>
  4. #include <type_traits>
  5. #include <stdexcept>
  6.  
  7. template<bool B>
  8. using Bool = std::integral_constant<bool, B>;
  9.  
  10. template<typename T>
  11. using EnableIf = typename std::enable_if<T::value>::type;
  12.  
  13. template<size_t N = 0, class Elem, class Traits, typename... Args, EnableIf<Bool<(N >= sizeof...(Args))>>...>
  14. inline void index_input(std::basic_istream<Elem,Traits>&, const size_t, const std::tuple<Args...>&) {
  15. throw std::out_of_range("Index exceeds number of arguments provided");
  16. }
  17.  
  18. template<size_t N = 0, class Elem, class Traits, typename... Args, EnableIf<Bool<(N < sizeof...(Args))>>...>
  19. inline void index_input(std::basic_istream<Elem,Traits>& in, const size_t i, const std::tuple<Args...>& tup) {
  20. if(i != N) {
  21. index_input<N + 1>(in, i, tup);
  22. return;
  23. }
  24. using std::get;
  25. in >> get<N>(tup);
  26. }
  27.  
  28. template<typename CharT, typename Elem, /*size_t N,*/ typename... Args>
  29. void fscan(std::basic_istream<CharT, Elem>& in, const std::basic_string<CharT, Elem>& format, Args&&... args) {
  30. // make a tuple of references
  31. auto tup = std::make_tuple(std::ref(std::forward<Args>(args))...);
  32. auto first = format.cbegin();
  33. auto last = format.cend();
  34. unsigned index = 0;
  35.  
  36. for(; first != last; ++first) {
  37. if(*first == '%' && ((first + 1) != last || *(first + 1) != '%')) {
  38. // format specifier
  39. index_input(in, index++, tup);
  40. continue;
  41. }
  42.  
  43. // non-format specifier or parsing error
  44. auto c = in.get();
  45. if(!in || c != *first) {
  46. throw std::runtime_error("error parsing");
  47. break;
  48. }
  49. }
  50. }
  51.  
  52. int main() {
  53. int x, y;
  54. fscan(std::cin, std::string("% = %"), x, y);
  55. std::cout << x << " = " << y;
  56. }
Success #stdin #stdout 0s 3436KB
stdin
10 = 11
stdout
10 = 11