summaryrefslogtreecommitdiff
path: root/indirect.h
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2016-11-20 11:27:07 +0100
committertomsmeding <tom.smeding@gmail.com>2016-11-20 11:27:07 +0100
commit3b390967e7c2ee4ac6d1a67c77f40ed43005e012 (patch)
tree4be72c3ed32277329c472c1dc72793577ea29195 /indirect.h
Initial
Diffstat (limited to 'indirect.h')
-rw-r--r--indirect.h157
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;
+}