diff options
Diffstat (limited to 'indirect.h')
-rw-r--r-- | indirect.h | 157 |
1 files changed, 157 insertions, 0 deletions
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 <stdexcept> + +using namespace std; + + +class NullIndirectError : public runtime_error{ +public: + NullIndirectError(); + NullIndirectError(const string &what_arg); + NullIndirectError(const char *what_arg); +}; + + +template <typename T> +class Indirect{ + T *ptr; + + class Dummy{}; + + Indirect(Dummy); + +public: + template <typename ...Args> + Indirect(Args... args); + + Indirect(const Indirect &other); + Indirect(Indirect &&other); + + ~Indirect(); + + Indirect<T>& operator=(const T &value); + Indirect<T>& operator=(T &&value); + + Indirect<T>& operator=(const Indirect<T> &other); + Indirect<T>& operator=(Indirect<T> &&other); + + bool isEmpty() const; + + T& operator*(); + const T& operator*() const; + + static Indirect<T> makeEmpty(); +}; + +template <typename T> +Indirect<T>::Indirect(Dummy) + :ptr(nullptr){} + +template <typename T> +Indirect<T> Indirect<T>::makeEmpty(){ + return Indirect<T>(Indirect::Dummy()); +}; + + +template <typename T> +template <typename ...Args> +Indirect<T>::Indirect(Args... args) + :ptr(new T(args...)){} + +template <typename T> +Indirect<T>::Indirect(const Indirect &other){ + if(!other.ptr){ + ptr=nullptr; + } else { + ptr=new T(*other.ptr); + } +} + +template <typename T> +Indirect<T>::Indirect(Indirect &&other){ + if(!other.ptr){ + ptr=nullptr; + } else { + ptr=new T(move(*other.ptr)); + other.ptr=nullptr; + } +} + +template <typename T> +Indirect<T>::~Indirect(){ + if(ptr){ + delete ptr; + } +} + + +template <typename T> +Indirect<T>& Indirect<T>::operator=(const T &value){ + if(!ptr){ + ptr=new T(value); + } else { + *ptr=value; + } + return *this; +} + +template <typename T> +Indirect<T>& Indirect<T>::operator=(T &&value){ + if(!ptr){ + ptr=new T(value); + } else { + *ptr=value; + } + return *this; +} + + +template <typename T> +Indirect<T>& Indirect<T>::operator=(const Indirect<T> &other){ + if(ptr){ + delete ptr; + } + if(!other.ptr){ + ptr=nullptr; + } else { + ptr=new T(*other.ptr); + } + return *this; +} + +template <typename T> +Indirect<T>& Indirect<T>::operator=(Indirect<T> &&other){ + if(ptr){ + delete ptr; + } + if(!other.ptr){ + ptr=nullptr; + } else { + ptr=new T(move(*other.ptr)); + other.ptr=nullptr; + } + return *this; +} + + +template <typename T> +bool Indirect<T>::isEmpty() const { + return ptr!=nullptr; +} + +template <typename T> +T& Indirect<T>::operator*(){ + if(!ptr){ + throw NullIndirectError(); + } + return *ptr; +} + +template <typename T> +const T& Indirect<T>::operator*() const { + if(!ptr){ + throw NullIndirectError(); + } + return *ptr; +} |