fork download
  1. #include <iostream>
  2. #include <stdexcept>
  3. #include <type_traits>
  4.  
  5. #define noexcept
  6.  
  7. namespace
  8. {
  9. enum class Block_Edges : int
  10. {
  11. from = 0,
  12. to = 4,
  13. };
  14. template<typename T, bool enable = std::is_enum<T>::value>
  15. int operator+(const T& e, int i)
  16. {
  17. //const T rei = i + static_cast<int>(e);
  18. const int rei = i + static_cast<int>(e);
  19. if (rei < static_cast<int>(T::from) || rei > static_cast<int>(T::to))
  20. {
  21. throw std::out_of_range("Addition to Row_Edges would create out of bounds index");
  22. }
  23. return rei;
  24. }
  25. template<typename T, bool enable = std::is_enum<T>::value>
  26. int operator-(const T& e, int i)
  27. {
  28. const int rei = i - static_cast<int>(e);
  29. if (rei < static_cast<int>(T::from) || rei > static_cast<int>(T::to))
  30. {
  31. throw std::out_of_range("Addition to Row_Edges would create out of bounds index");
  32. }
  33. return rei;
  34. }
  35.  
  36. template<typename T, bool enable = std::is_enum<T>::value>
  37. int& operator++(T& e)
  38. {
  39. return e = static_cast<int>(e + 1);
  40. }
  41.  
  42. #if 0 //this does not do the right thing
  43. template<typename T, bool enable = std::is_enum<T>::value>
  44. const int& operator*(T& e)
  45. {
  46. return static_cast<int>(e);
  47. }
  48. #endif
  49. };
  50.  
  51. template<typename T, bool enable = std::is_integral<T>::value || std::is_enum<T>::value>
  52. struct range_impl
  53. {
  54. struct iterator
  55. {
  56. const T operator * ()const noexcept
  57. {
  58. return value;
  59. }
  60.  
  61. iterator& operator ++() noexcept
  62. {
  63. ++value;
  64. return *this;
  65. }
  66.  
  67. friend const bool operator != (const iterator& lhs, const iterator& rhs) noexcept
  68. {
  69. return lhs.value != rhs.value;
  70. }
  71.  
  72. T value;
  73. };
  74.  
  75. std::size_t size() const
  76. {
  77. return last - first;
  78. }
  79.  
  80. const iterator begin()const noexcept
  81. {
  82. return{ first };
  83. }
  84.  
  85. const iterator end()const noexcept
  86. {
  87. return{ last };
  88. }
  89.  
  90. T first;
  91. T last;
  92. };
  93.  
  94. template<typename T>
  95. struct range_impl<T, false>
  96. {
  97. range_impl(T first, T last)
  98. : first(first)
  99. , last(last)
  100. {}
  101.  
  102. std::size_t size() const
  103. {
  104. return std::distance(first, last);
  105. }
  106.  
  107. const T begin()const noexcept
  108. {
  109. return{ first };
  110. }
  111.  
  112. const T end()const noexcept
  113. {
  114. return{ last };
  115. }
  116.  
  117. T first;
  118. T last;
  119. };
  120.  
  121. //template<typename T>
  122. //range_impl<T> range(T first, T last) noexcept
  123. //{
  124. // return{ first, last };
  125. //}
  126. template<typename T1, typename T2>
  127. range_impl<typename std::common_type<T1, T2>::type>
  128. range(T1 first, T2 last) noexcept
  129. {
  130. return{ first, last };
  131. }
  132.  
  133. int main()
  134. {
  135. for (const auto& i : range(Block_Edges::from - 1, Block_Edges::to + 1)) //succeeds
  136. {
  137. std::cout << '\n' << i << ':';
  138. for (const auto& j : range(Block_Edges::from - 2, Block_Edges::to + 0))
  139. {
  140. std::cout << j << ' ';
  141. }
  142. }
  143. }
Runtime error #stdin #stdout #stderr 0s 3268KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
terminate called after throwing an instance of 'std::out_of_range'
  what():  Addition to Row_Edges would create out of bounds index