From 3b390967e7c2ee4ac6d1a67c77f40ed43005e012 Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Sun, 20 Nov 2016 11:27:07 +0100 Subject: Initial --- indirect.h | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 indirect.h (limited to 'indirect.h') diff --git a/indirect.h b/indirect.h new file mode 100644 index 0000000..da93955 --- /dev/null +++ b/indirect.h @@ -0,0 +1,157 @@ +#pragma once + +#include + +using namespace std; + + +class NullIndirectError : public runtime_error{ +public: + NullIndirectError(); + NullIndirectError(const string &what_arg); + NullIndirectError(const char *what_arg); +}; + + +template +class Indirect{ + T *ptr; + + class Dummy{}; + + Indirect(Dummy); + +public: + template + Indirect(Args... args); + + Indirect(const Indirect &other); + Indirect(Indirect &&other); + + ~Indirect(); + + Indirect& operator=(const T &value); + Indirect& operator=(T &&value); + + Indirect& operator=(const Indirect &other); + Indirect& operator=(Indirect &&other); + + bool isEmpty() const; + + T& operator*(); + const T& operator*() const; + + static Indirect makeEmpty(); +}; + +template +Indirect::Indirect(Dummy) + :ptr(nullptr){} + +template +Indirect Indirect::makeEmpty(){ + return Indirect(Indirect::Dummy()); +}; + + +template +template +Indirect::Indirect(Args... args) + :ptr(new T(args...)){} + +template +Indirect::Indirect(const Indirect &other){ + if(!other.ptr){ + ptr=nullptr; + } else { + ptr=new T(*other.ptr); + } +} + +template +Indirect::Indirect(Indirect &&other){ + if(!other.ptr){ + ptr=nullptr; + } else { + ptr=new T(move(*other.ptr)); + other.ptr=nullptr; + } +} + +template +Indirect::~Indirect(){ + if(ptr){ + delete ptr; + } +} + + +template +Indirect& Indirect::operator=(const T &value){ + if(!ptr){ + ptr=new T(value); + } else { + *ptr=value; + } + return *this; +} + +template +Indirect& Indirect::operator=(T &&value){ + if(!ptr){ + ptr=new T(value); + } else { + *ptr=value; + } + return *this; +} + + +template +Indirect& Indirect::operator=(const Indirect &other){ + if(ptr){ + delete ptr; + } + if(!other.ptr){ + ptr=nullptr; + } else { + ptr=new T(*other.ptr); + } + return *this; +} + +template +Indirect& Indirect::operator=(Indirect &&other){ + if(ptr){ + delete ptr; + } + if(!other.ptr){ + ptr=nullptr; + } else { + ptr=new T(move(*other.ptr)); + other.ptr=nullptr; + } + return *this; +} + + +template +bool Indirect::isEmpty() const { + return ptr!=nullptr; +} + +template +T& Indirect::operator*(){ + if(!ptr){ + throw NullIndirectError(); + } + return *ptr; +} + +template +const T& Indirect::operator*() const { + if(!ptr){ + throw NullIndirectError(); + } + return *ptr; +} -- cgit v1.2.3-70-g09d2