#pragma once
#include "a83/macro.hpp"
#ifdef DEBUG
#include <cassert>
#endif
//! индекс с барьером в начале и в конце, который идёт по кругу
template<class T, const T START, const T END>
class Bounded {
private:
  T val = 0;
  Bounded& operator = (CN(Bounded)) = delete;
  Bounded(CN(Bounded)) = delete;
public:
  T start() const { return START; }
  T end() const { return END; }
  T size() const { return END - START; }
  Bounded(): val(START) {
    #ifdef DEBUG
    static_assert(START <= END);
    #endif
  }
  Bounded(CN(T) _val): val(_val) {
    #ifdef DEBUG
    assert(_val >= START && _val <= END);
    static_assert(START <= END);
    #endif
  }
  void operator ++() {
    ++val;
    if (val > END)
      val = START + val - END - 1; 
  }
  void operator --() {
    --val;
    if (val < START)
      val = END - val + START - 1; 
  }
  CN(T) operator () () const { return val; }
}; // Bounded
