#include <utility>
#include <cstddef>
#include <algorithm>

class ScopedIntArray // этот класс нельзя копировать, то можно перемещать
{
public:
    explicit ScopedIntArray(size_t n)
        : raw_(new int[n]()), size_(n)
    { }
    ScopedIntArray()
        : raw_(nullptr), size_(0)
    { }

    ~ScopedIntArray()
    {
        delete[] raw_;
    }
    int & operator[](size_t idx)
    {
        return raw_[idx];
    }
    int operator[](size_t idx) const
    {
        return raw_[idx];
    }
    size_t size() const
    {
        return size_;
    }
    int * begin() const
    {
        return raw_;
    }
    int * end() const
    {
        return raw_ + size_;
    }
    // Из-за того, что мы не определяли свои
    // собственные оператор присваивания\конструктор компирования
    // генерируемые по-умолчанию были автоматически помечены как deleted,
    // поэтому в этом случае яное указание noncopyable не требуется.

    ScopedIntArray(ScopedIntArray && other)
        : raw_(other.raw_), size_(other.size_)
    {
        other.raw_  = 0;
        other.size_ = 0;
    }
    ScopedIntArray & operator=(ScopedIntArray && other)
    {
        if(this != &other)
        {
            std::swap(raw_, other.raw_);
            std::swap(size_, other.size_);
        }
        return *this;
    }

private:
    int *  raw_;
    size_t size_;
};

class ScopedIntArrayExt // этот класс можно копировать и перемещать
    : public ScopedIntArray
{
public:
    ScopedIntArrayExt()
        : ScopedIntArray(), additionalData_(false)
    { }
    explicit ScopedIntArrayExt(size_t n, bool additionalData = false)
        : ScopedIntArray(n), additionalData_(additionalData)
    { }
    ScopedIntArrayExt(ScopedIntArrayExt const & other)
        : ScopedIntArray(other.size()), additionalData_(other.additionalData_)
    {
        std::copy(other.begin(), other.end(), begin());
    }
    ScopedIntArrayExt & operator=(ScopedIntArrayExt const & other)
    {
        if(this != &other)
        {
            ScopedIntArray::operator=(ScopedIntArrayExt(other)); // copy-and-swap idiom
            additionalData_ = other.additionalData_;
        }
        return *this;
    }

private:
    bool additionalData_;
};

int main()
{
    ScopedIntArray arr(30);
    arr[10] = 2;

    //ScopedIntArray arr1 = arr; // ERROR use of deleted function 'ScopedIntArray::ScopedIntArray(const ScopedIntArray&)'
    ScopedIntArray arr1 = std::move(arr); // ОК, перемещение

    ScopedIntArray arr2;

    //arr = arr2; // ERROR: use of deleted function 'ScopedIntArray& ScopedIntArray::operator=(const ScopedIntArray&)'
    arr = std::move(arr2); // ОК, перемещение

    ScopedIntArrayExt arr3(30);
    arr3[11] = 3;

    ScopedIntArrayExt arr4 = arr3; // OK, копирование
    ScopedIntArrayExt arr5 = std::move(arr3); // OK, перемещение
    ScopedIntArrayExt arr6;

    arr3 = arr6; // ОК, присваивание
    arr3 = std::move(arr6); // ОК, перемещение
}