#include <algorithm>
#include <cstring>
#include <iostream>
#include <memory>
using namespace std;
template <class X>
class ExArray {
public:
virtual X& operator [](const unsigned int& i) = 0;
virtual X& at(const unsigned int& i) = 0;
virtual unsigned int getSize() const = 0;
virtual bool isEmpty() const = 0;
virtual void push(const X& x) = 0;
virtual void pop() = 0;
virtual void clear() = 0;
virtual void resize(const unsigned int& sz) = 0;
};
template <class X>
class PrimitiveExArray : public ExArray<X> {
public:
PrimitiveExArray(const unsigned int& sz = 0);
virtual ~PrimitiveExArray();
virtual X& operator [](const unsigned int& i);
virtual X& at(const unsigned int& i);
virtual unsigned int getSize() const;
virtual bool isEmpty() const;
virtual void push(const X& x);
virtual void pop();
virtual void clear();
virtual void resize(const unsigned int& sz);
protected:
X* buf;
unsigned int buf_sz;
unsigned int sz;
};
template <class X>
class ClassObjectExArray : public ExArray<X> {
public:
ClassObjectExArray(const unsigned int& sz = 0);
virtual ~ClassObjectExArray();
virtual X& operator [](const unsigned int& i);
virtual X& at(const unsigned int& i);
virtual unsigned int getSize() const;
virtual bool isEmpty() const;
virtual void push(const X& x);
virtual void pop();
virtual void clear();
virtual void resize(const unsigned int& sz);
protected:
X* buf;
unsigned int buf_sz;
unsigned int sz;
};
template <class X>
PrimitiveExArray<X>::PrimitiveExArray(const unsigned int& sz) : buf(nullptr), buf_sz(0), sz(0) {
resize(sz);
}
template <class X>
PrimitiveExArray<X>::~PrimitiveExArray() {
if (this->buf) delete[] this->buf;
}
template <class X>
X& PrimitiveExArray<X>::operator [](const unsigned int& i) {
return this->buf[i];
}
template <class X>
X& PrimitiveExArray<X>::at(const unsigned int& i) {
return this->buf[i];
}
template <class X>
unsigned int PrimitiveExArray<X>::getSize() const {
return this->sz;
}
template <class X>
bool PrimitiveExArray<X>::isEmpty() const {
return this->sz == 0;
}
template <class X>
void PrimitiveExArray<X>::push(const X& x) {
resize(this->sz + 1);
this->buf[this->sz - 1] = x;
}
template <class X>
void PrimitiveExArray<X>::pop() {
this->sz--;
}
template <class X>
void PrimitiveExArray<X>::clear() {
this->sz = 0;
}
template <class X>
void PrimitiveExArray<X>::resize(const unsigned int& sz) {
if (sz > this->buf_sz) {
unsigned int new_buf_sz = sz << 1;
X* new_buf = new X[new_buf_sz];
if (this->buf_sz != 0) {
memcpy(new_buf, this->buf, sizeof(X) * this->sz);
delete[] this->buf;
}
this->buf = new_buf;
this->buf_sz = new_buf_sz;
}
this->sz = sz;
}
template <class X>
ClassObjectExArray<X>::ClassObjectExArray(const unsigned int& sz) : buf(nullptr), buf_sz(0), sz(0) {
resize(sz);
}
template <class X>
ClassObjectExArray<X>::~ClassObjectExArray() {
if (this->buf) delete[] this->buf;
}
template <class X>
X& ClassObjectExArray<X>::operator [](const unsigned int& i) {
return this->buf[i];
}
template <class X>
X& ClassObjectExArray<X>::at(const unsigned int& i) {
return this->buf[i];
}
template <class X>
unsigned int ClassObjectExArray<X>::getSize() const {
return this->sz;
}
template <class X>
bool ClassObjectExArray<X>::isEmpty() const {
return this->sz == 0;
}
template <class X>
void ClassObjectExArray<X>::push(const X& x) {
resize(this->sz + 1);
this->buf[this->sz - 1] = x;
}
template <class X>
void ClassObjectExArray<X>::pop() {
this->buf[this->sz - 1] = X();
this->sz--;
}
template <class X>
void ClassObjectExArray<X>::clear() {
for (unsigned int i = 0; i < this->sz; i++) this->buf[i] = X();
this->sz = 0;
}
template <class X>
void ClassObjectExArray<X>::resize(const unsigned int& sz) {
if (sz > this->buf_sz) {
unsigned int new_buf_sz = sz << 1;
X* new_buf = new X[new_buf_sz];
if (this->buf_sz != 0) {
copy(this->buf, this->buf + this->sz, new_buf);
delete[] this->buf;
}
this->buf = new_buf;
this->buf_sz = new_buf_sz;
}
this->sz = sz;
}
class Hoge {
public:
int n;
Hoge(const int& n = 0) : n(n) { cout << "Hoge(const int& n = 0) : n=" << this->n << endl; }
Hoge(const Hoge& a) : n(a.n) { cout << "Hoge(const Hoge& a) : n=" << this->n << endl; }
virtual ~Hoge() { cout << "virtual ~Hoge() : n=" << this->n << endl; }
Hoge& operator =(const Hoge& a) { cout << "Hoge& operator =(const Hoge& a) : a.n=" << a.n << ", n=" << this->n << endl; this->n = a.n; return *this; }
operator int() const { return this->n; }
};
template <class X> static void print(const shared_ptr<ExArray<X> >& a) {
cout << "size=" << a->getSize() << endl;
for (unsigned int i = 0; i < a->getSize(); i++)
cout << "[" << i << "]=" << (int)a->at(i) << endl;
cout << endl;
}
int main() {
{
shared_ptr<ExArray<int> > a(new PrimitiveExArray<int>(1));
print(a);
a->push(1);
a->push(23);
a->push(456);
print(a);
a->at(1) = 7;
a->pop();
print(a);
a->resize(10);
a->at(2) = 8;
a->at(3) = 9;
a->at(4) = 10;
a->resize(7);
print(a);
a->clear();
print(a);
}
{
shared_ptr<ExArray<Hoge> > a(new ClassObjectExArray<Hoge>(1));
print(a);
a->push(Hoge(1));
a->push(Hoge(23));
a->push(Hoge(456));
print(a);
a->at(1) = Hoge(7);
a->pop();
print(a);
a->resize(10);
a->at(2) = Hoge(8);
a->at(3) = Hoge(9);
a->at(4) = Hoge(10);
a->resize(7);
print(a);
a->clear();
print(a);
}
return 0;
}