Pointer handle - follow-up
c++11 Allows constructor chaining:

Ptr(const Ptr&amp; t) {
    sz = t.sz;
    p = new T[sz];
    T* x = t.get();
    for (int i = 0; i &lt; sz; ++i) {
        p[i] = x[i];
    }
}


Can be written as:

Ptr(const Ptr&amp; t): Ptr(t.p, t.sz) {}


Good to see you using the copy and swap idiom.

Ptr&amp; operator=(const Ptr&amp; t) {
    Ptr copy{t};
    std::swap(copy.sz, sz);
    std::swap(copy.p, p);
    return *this;
}


But his can be simlified by making the compiler to the copy.

Ptr&amp; operator=(Ptr copy) {
        //   ^^^^^    Pass by value is generating a copy.       
    std::swap(copy.sz, sz);
    std::swap(copy.p, p);
    return *this;
}


This looks good.

~Ptr() {
    delete[] p;
}


But you ca still move p

void operator+=(int i) {
    check_range(index+i);
    index += i;
    p+= i;               // P has changed
}

void operator-=(int i) {
    check_range(index-i);
    index -= i;
    p -= i;               // P has changed
}


Thus using it with delete after the point it changed is going to cause UB.