#include <type_traits>
#include <exception>
class NonCopyable
{
public:
NonCopyable(const NonCopyable&) = delete;
NonCopyable(NonCopyable&&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;
NonCopyable& operator=(NonCopyable&&) = delete;
~NonCopyable() = default;
protected:
NonCopyable() = default;
};
template <typename T>
class Subsystem : NonCopyable
{
public:
template<class ...Args>
static bool Create(Args&& ...args)
{
if( IsValid() )
throw ("Trying to create an already created module.");
instance() = new T(std::forward<Args>(args)...);
isCreate() = true;
return IsValid();
}
template<typename SubClass, class ...Args>
static bool Create(Args&& ...args)
{
if( IsValid() )
throw ("Trying to create an already created module.");
instance() = static_cast<T*>(new SubClass(std::forward<Args>(args)...));
isCreate() = true;
return IsValid();
}
static void Destroy()
{
delete instance();
valid() = false;
isCreate() = false;
}
static T& Get()
{
if( !IsValid() )
throw ("Trying to access a module but it hasn't been created up yet.");
return *instance();
}
static const bool IsValid()
{
return valid() && isCreate();
}
protected:
Subsystem() = default;
~Subsystem() = default;
static T*& instance()
{
static T* inst = nullptr;
return inst;
}
static bool& valid()
{
static bool inst = false;
return inst;
}
static bool& isCreate()
{
static bool inst = false;
return inst;
}
static void setValid(bool bvalid)
{
valid() = bvalid;
}
};
template <typename T>
inline T& GetSubsystem()
{
return T::Get();
}
class Foo1 : public Subsystem<Foo1>
{
public:
Foo1(int ni) : i(ni)
{
if (i == 0)
return;
setValid(true);
}
int i;
void Bar(){i = i + 10;}
};
class Foo2 : public Subsystem<Foo2>
{
public:
Foo2(int nx, int ny) : x(nx), y(ny) {setValid(true);}
int x,y;
};
class Foo3 : public Subsystem<Foo3>
{
public:
Foo3(float nf) : f(nf) {setValid(true);}
float f;
};
int main()
{
Foo1::Create(10);
Foo2::Create(10,20);
Foo3::Create(10.4f);
GetSubsystem<Foo1>().Bar();
Foo3::Destroy();
Foo2::Destroy();
Foo1::Destroy();
return 0;
}