#ifndef HOLDER_H
#define HOLDER_H
#include <cassert>
// Note: Currently supports objects with zero, one or two parameter c'tors
template <class T>
class Holder {
public:
Holder():created(false)
{
}
~Holder() {
destroy();
}
Holder(const Holder<T> &other) {
create(other);
}
Holder<T> & operator=(const Holder<T> &other) {
if (this == &other) {
return *this;
}
// Not sure if the asserts are a good idea...
assert(created);
assert(other.created);
getObj() = other.getObj();
return *this;
}
void destroy() {
if (created) {
created = false;
getObj().~T();
}
}
T* operator->() {
assert(created);
return &getObj();
}
const T* operator->() const {
assert(created);
return &getObj();
}
T & operator*() {
assert(created);
return getObj();
}
const T & operator*() const {
assert(created);
return getObj();
}
void create() {
new (obj) T;
created = true;
}
template <class P1>
void create(const P1 &p1) {
new (obj) T(p1);
created = true;
}
template <class P1, class P2>
void create(const P1 &p1, const P2 &p2) {
new (obj) T(p1, p2);
created = true;
}
private:
T& getObj() {
return *(reinterpret_cast<T*>(obj));
}
const T& getObj() const {
return (const_cast<Holder<T>*>(this))->getObj();
}
char obj[sizeof(T)];
bool created;
};
#endif // HOLDER_H
#include "Holder.h"
#include <iostream>
#include <string>
using namespace std;
struct Student {
string name;
int grade;
Student(const string &name, int grade)
: name(name), grade(grade)
{
cout << "Student::Student() for " << name << endl;
}
~Student() {
cout << "Student::~Student() for " << name << endl;
}
void print() const {
cout << name << ", " << grade << endl;
}
};
void main() {
Holder<Student> st1;
Holder<Student> st2;
cout << "Hello" << endl;
st1.create("John", 87);
st2.create("Mike", 92);
st1->print();
(*st2).print();
st2 = st1;
st2->print();
st1.destroy();
st1.destroy(); // Does nothing
// No call to st2.destroy();
cout << "Goodbye" << endl;
}