00001 00026 #ifndef GALOIS_OPTIONAL_H 00027 #define GALOIS_OPTIONAL_H 00028 00029 #include "Galois/LazyObject.h" 00030 #include <cassert> 00031 00032 namespace Galois { 00033 00037 template<typename T> 00038 class optional { 00039 LazyObject<T> data_; 00040 bool initialized_; 00041 00042 void construct(const T& val) { 00043 data_.construct(val); 00044 initialized_ = true; 00045 } 00046 00047 void assign_impl(const T& val) { get_impl() = val; } 00048 00049 void destroy() { 00050 if (initialized_) { 00051 data_.destroy(); 00052 initialized_ = false; 00053 } 00054 } 00055 00056 T& get_impl() { return data_.get(); } 00057 const T& get_impl() const { return data_.get(); } 00058 00059 public: 00060 typedef bool (optional::*unspecified_bool_type)() const; 00061 00062 optional(): initialized_(false) { } 00063 00064 optional(const T& val): initialized_(false) { 00065 construct(val); 00066 } 00067 00068 optional(const optional& rhs): initialized_(false) { 00069 if (rhs.is_initialized()) 00070 construct(rhs.get_impl()); 00071 } 00072 00073 template<typename U> 00074 explicit optional(const optional<U>& rhs): initialized_(false) { 00075 assign(rhs); 00076 } 00077 00078 ~optional() { destroy(); } 00079 00080 void assign(const optional& rhs) { 00081 if (is_initialized()) { 00082 if (rhs.is_initialized()) 00083 assign_impl(rhs.get_impl()); 00084 else 00085 destroy(); 00086 } else { 00087 if (rhs.is_initialized()) 00088 construct(rhs.get_impl()); 00089 } 00090 } 00091 00092 template<typename U> 00093 void assign(const optional<U>& rhs) { 00094 if (is_initialized()) { 00095 if (rhs.is_initialized()) 00096 assign_impl(rhs.get_impl()); 00097 else 00098 destroy(); 00099 } else { 00100 if (rhs.is_initialized()) 00101 construct(rhs.get_impl()); 00102 } 00103 } 00104 00105 void assign(const T& val) { 00106 if (is_initialized()) 00107 assign_impl(val); 00108 else 00109 construct(val); 00110 } 00111 00112 bool is_initialized() const { return initialized_; } 00113 00114 optional& operator=(const optional& rhs) { 00115 assign(rhs); 00116 return *this; 00117 } 00118 00119 template<typename U> 00120 optional& operator=(const optional<U>& rhs) { 00121 assign(rhs); 00122 return *this; 00123 } 00124 00125 optional& operator=(const T& val) { 00126 assign(val); 00127 return *this; 00128 } 00129 00130 T& get() { assert(initialized_); return get_impl(); } 00131 const T& get() const { assert(initialized_); return get_impl(); } 00132 T& operator*() { return get(); } 00133 const T& operator*() const { return get(); } 00134 T* operator->() { assert(initialized_); return &get_impl(); } 00135 const T* operator->() const { assert(initialized_); return &get_impl(); } 00136 00137 operator unspecified_bool_type() const { return initialized_ ? &optional::is_initialized : 0; } 00138 }; 00139 00140 } 00141 00142 #endif