// memory test
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
// model values = atom int | array value*
static constexpr size_t roundup(size_t x, size_t m)
{
return x % m == 0 ? x : (x + m) / m * m;
};
class Value;
typedef std::shared_ptr<Value> ValuePtr;
class Value {
public:
Value() = default;
virtual ~Value() {
}
};
class Atom: public Value {
public:
Atom(const int v): _value(v) {
}
virtual ~Atom() {
}
static ValuePtr create(const int v) {
return std::shared_ptr<Atom>(new Atom(v));
}
private:
int _value;
};
struct ValueField {
ValuePtr _value;
};
class Array: public Value {
public:
Array() = default;
virtual ~Array() {
while (_size-- > 0)
std::addressof(operator[](_size))->~ValueField();
}
ValueField &operator[](size_t i) {
char *r0 = reinterpret_cast<char *>(this) + roundup(sizeof(*this), alignof(ValueField));
ValueField *t0 = reinterpret_cast<ValueField *>(r0);
return t0[i];
}
ValueField &at(size_t i) {
if (i >= _size)
throw std::out_of_range("duuude!");
return operator[](i);
}
static ValuePtr create(size_t _sizes) {
return std::shared_ptr<Array>(new(_sizes) Array(_sizes));
}
void *operator new(size_t count, size_t _sizes) {
auto z = roundup(count, alignof(ValueField)) + sizeof(ValueField) * _sizes;
return ::operator new(z);
}
void operator delete(void *x) {
::operator delete(x);
}
// not implemented for brevity reasons.
// Also, it would have to handle (if only to throw an exception)
// if someone attempted to move an Array(30) into an Array(20)
/*
Array(Array &&) = delete;
void operator=(Array &&) = delete;
*/
private:
Array(size_t n) {
for (_size = 0; _size < n; ++_size)
new(std::addressof(operator[](_size))) ValueField;
}
size_t _size = 0;
};
int main()
{
Array fixed;
auto flex = Array::create(20);
// (*flex)[1]._value = 42;
}
No comments:
Post a Comment