Q: C++ replacement: Replacing every occurence of v[x] with v.at(x) In C++, for a vector v, v.at(x) behaves like v[x], except that it throws an out of bounds error if a non-existent element is accessed.
I would like to ideally always use v.at(x), however, it is not as convenient to write as v[x]. Is there a way I can make v[x] behave like v.at(x), perhaps using something like #define?
If not, is there a better solution for out-of-bounds errors to always be thrown?

A: You may consider overloading the method in a new inheritance, as follows
#include <iostream>
#include <vector>

template< class T, class allocator =  std::allocator<T>>
struct Vector : std::vector<T, allocator>{
    using std::vector<T, allocator>::vector;

    const T& operator[](size_t i)const{
        return this -> at(i);
    }

    T& operator[](size_t i){
        return this -> at(i);
    }
};

template< class T>
Vector(size_t, T ) -> Vector<T>;//if u want to use c++17 deduction guides

int main()
{
    std::vector<int> vec1(4,1);
    std::cout << vec1[4];

    Vector vec2(4,1);
    std::cout << vec2[4];

}



A: You can use a proxy object with operator [] that calls method at(). Of course, this is not exactly what you want, but the syntax is similar: instead of v[x] you have to write at(v)[x].
Proof of concept:
#include <iostream>
#include <vector>


template<class T>
class AtProxy
{
  public:
    AtProxy(const AtProxy<T>& proxy) : m_obj{proxy.m_obj} {}
    AtProxy(T& obj) : m_obj{obj} {}
    typename T::reference operator [](size_t index)
    {
      return m_obj.at(index);
    }
  private:
    T& m_obj;
};


template<class T>
AtProxy<T> at(T& v)
{
  return AtProxy<T>(v);
}


int main()
{
  try
  {
    std::vector<int> vec = {1,2,3,4,5};

    for(size_t i = 0; i < 5; i++)   
    {
      std::cout << i << std::endl;
      at(vec)[i] = at(vec)[i + 1] + 1;
    }   
  }
  catch(std::exception& e)
  {
    std::cout << "exception: " << e.what() << std::endl;
  }
   
  std::cout << "ok" << std::endl;
  return 0;
}

