Honeycomb  0.1
Component-Model Framework
Optional.h
Go to the documentation of this file.
1 // Honeycomb, Copyright (C) 2015 NewGamePlus Inc. Distributed under the Boost Software License v1.0.
2 #pragma once
3 
4 #include "Honey/Misc/Debug.h"
5 
6 namespace honey
7 {
8 
10 struct optnull_t {};
13 
15 
51 template<class T>
52 class optional
53 {
54  template<class T_> friend class optional;
55 public:
57  optional() : _val(nullptr) {}
58  optional(optnull_t) : _val(nullptr) {}
59  optional(const optional& rhs) : _val(nullptr) { if (rhs._val) construct(rhs.get()); }
60  optional(optional& rhs) : _val(nullptr) { if (rhs._val) construct(rhs.get()); }
61  optional(optional&& rhs) : _val(nullptr) { if (rhs._val) construct(move(rhs.get())); }
62  template<class U> optional(const optional<U>& rhs) : _val(nullptr) { if (rhs._val) construct(rhs.get()); }
63  template<class U> optional(optional<U>& rhs) : _val(nullptr) { if (rhs._val) construct(rhs.get()); }
64  template<class U> optional(optional<U>&& rhs) : _val(nullptr) { if (rhs._val) construct(move(rhs.get())); }
65  template<class U> optional(U&& rhs) : _val(nullptr) { construct(forward<U>(rhs)); }
66 
67  ~optional() { uninit(); }
68 
70  optional& operator=(optnull_t) { uninit(); return *this; }
71 
73  optional& operator=(const optional& rhs) { return operator=<T>(rhs); }
74  optional& operator=(optional& rhs) { return operator=<T>(rhs); }
75  optional& operator=(optional&& rhs) { return operator=<T>(move(rhs)); }
76  template<class U> optional& operator=(const optional<U>& rhs) { if (rhs._val) operator=(rhs.get()); else uninit(); return *this; }
77  template<class U> optional& operator=(optional<U>& rhs) { if (rhs._val) operator=(rhs.get()); else uninit(); return *this; }
78  template<class U> optional& operator=(optional<U>&& rhs) { if (rhs._val) operator=(move(rhs.get())); else uninit(); return *this; }
79 
81 
84  template<class U> optional& operator=(U&& rhs) { if (!_val) construct(forward<U>(rhs)); else get() = forward<U>(rhs); return *this; }
85 
86  bool operator==(optnull_t) const { return !_val; }
87  bool operator!=(optnull_t) const { return !operator==(optnull); }
88 
89  const T& operator*() const { return get(); }
90  T& operator*() { return get(); }
91  const T* operator->() const { return &get(); }
92  T* operator->() { return &get(); }
93  operator const T&() const { return get(); }
94  operator T&() { return get(); }
95 
97  explicit operator bool() const { return _val; }
98  explicit operator bool() { return _val; }
99 
101  const T& get() const { assert(_val, "Optional not initialized"); return *_val; }
102  T& get() { assert(_val, "Optional not initialized"); return *_val; }
103 
105  const T* ptr() const { return _val; }
106  T* ptr() { return _val; }
107 
108  friend ostream& operator<<(ostream& os, const optional& rhs) { if (!rhs) return os << "optnull"; return os << *rhs; }
109 
110 private:
112  typedef typename std::aligned_storage<sizeof(T), alignof(T)>::type Storage;
113 
114  template<class U>
115  void construct(U&& rhs) { _val = reinterpret_cast<T*>(&_storage); new (&_storage) T(forward<U>(rhs)); }
117  void uninit() { if (!_val) return; get().~T(); _val = nullptr; }
118 
119  T* _val;
120  Storage _storage;
121 };
122 
124 
131 template<class T>
132 class optional<T&>
133 {
134  template<class T_> friend class optional;
135 public:
136  optional() : _val(nullptr) {}
137  optional(T* rhs) : _val(nullptr) { bind(rhs); }
138  optional(optnull_t) : _val(nullptr) {}
139  optional(const optional& rhs) : _val(nullptr) { bind(rhs._val); }
140  optional(optional& rhs) : _val(nullptr) { bind(rhs._val); }
141  optional(optional&& rhs) : _val(nullptr) { bind(rhs._val); }
142  template<class U> optional(const optional<U>& rhs) : _val(nullptr) { bind(rhs._val); }
143  template<class U> optional(optional<U>& rhs) : _val(nullptr) { bind(rhs._val); }
144  template<class U> optional(optional<U>&& rhs) : _val(nullptr) { bind(rhs._val); }
145  template<class U> optional(U&& rhs) : _val(nullptr) { bind(forward<U>(rhs)); }
146 
148  template<class U> void bind(U&& rhs) { bind(&rhs); }
150  template<class U> void bind(U* rhs) { _val = rhs; }
152  void bind(nullptr_t) { _val = nullptr; }
153 
155  optional& operator=(optnull_t) { bind(nullptr); return *this; }
156 
158  optional& operator=(const optional& rhs) { return operator=<T&>(rhs); }
159  optional& operator=(optional& rhs) { return operator=<T&>(rhs); }
160  optional& operator=(optional&& rhs) { return operator=<T&>(move(rhs)); }
161  template<class U> optional& operator=(const optional<U>& rhs) { if (rhs._val) operator=(rhs.get()); return *this; }
162  template<class U> optional& operator=(optional<U>& rhs) { if (rhs._val) operator=(rhs.get()); return *this; }
163  template<class U> optional& operator=(optional<U>&& rhs) { if (rhs._val) operator=(move(rhs.get())); return *this; }
164 
166  template<class U> optional& operator=(U&& rhs) { get() = forward<U>(rhs); return *this; }
167 
168  bool operator==(optnull_t) const { return !_val; }
169  bool operator!=(optnull_t) const { return !operator==(optnull); }
170 
171  const T& operator*() const { return get(); }
172  T& operator*() { return get(); }
173  const T* operator->() const { return &get(); }
174  T* operator->() { return &get(); }
175  operator const T&() const { return get(); }
176  operator T&() { return get(); }
177 
178  explicit operator bool() const { return _val; }
179  explicit operator bool() { return _val; }
180 
181  const T& get() const { assert(_val, "Optional not initialized"); return *_val; }
182  T& get() { assert(_val, "Optional not initialized"); return *_val; }
183 
184  const T* ptr() const { return _val; }
185  T* ptr() { return _val; }
186 
187  friend ostream& operator<<(ostream& os, const optional& rhs) { if (!rhs) return os << "optnull"; return os << *rhs; }
188 
189 private:
190  T* _val;
191 };
192 
193 }
optional(const optional &rhs)
Definition: Optional.h:139
optional & operator=(optional &rhs)
Definition: Optional.h:159
T * operator->()
Definition: Optional.h:92
void bind(nullptr_t)
Unbinds object.
Definition: Optional.h:152
~optional()
Definition: Optional.h:67
optional & operator=(optnull_t)
Unbinds object.
Definition: Optional.h:155
optional & operator=(optional &&rhs)
Definition: Optional.h:160
static optnull_t optnull
Null optional, use to reset an optional to an uninitialized state or test for initialization.
Definition: Optional.h:12
optional(const optional &rhs)
Definition: Optional.h:59
bool operator!=(optnull_t) const
Definition: Optional.h:169
friend ostream & operator<<(ostream &os, const optional &rhs)
Definition: Optional.h:187
optional()
Uninitialized by default.
Definition: Optional.h:57
optional(optional &rhs)
Definition: Optional.h:140
optional & operator=(optnull_t)
Reset the optional to an uninitialized state.
Definition: Optional.h:70
const T & get() const
Get wrapped object. Optional must be initialized.
Definition: Optional.h:101
friend ostream & operator<<(ostream &os, const optional &rhs)
Definition: Optional.h:108
const T * operator->() const
Definition: Optional.h:91
optional & operator=(U &&rhs)
Assign object. On the first assignment the instance is copy/move constructed, assignments thereafter ...
Definition: Optional.h:84
void bind(U *rhs)
Bind wrapped reference from object pointer. Unbinds if pointer is null.
Definition: Optional.h:150
bool operator==(optnull_t) const
Definition: Optional.h:86
void bind(U &&rhs)
Bind wrapped reference to object.
Definition: Optional.h:148
optional & operator=(optional< U > &&rhs)
Definition: Optional.h:163
optional & operator=(optional< U > &rhs)
Definition: Optional.h:77
optional(const optional< U > &rhs)
Definition: Optional.h:142
optional & operator=(optional &&rhs)
Definition: Optional.h:75
optional(optional< U > &rhs)
Definition: Optional.h:63
optional(const optional< U > &rhs)
Definition: Optional.h:62
T & operator*()
Definition: Optional.h:172
const T * ptr() const
Get pointer to wrapped object. Returns null if not initialized.
Definition: Optional.h:105
optional(optional< U > &rhs)
Definition: Optional.h:143
optional(optional &rhs)
Definition: Optional.h:60
optional(optnull_t)
Definition: Optional.h:58
optional(U &&rhs)
Definition: Optional.h:65
T * operator->()
Definition: Optional.h:174
optional()
Definition: Optional.h:136
const T * operator->() const
Definition: Optional.h:173
Null optional type.
Definition: Optional.h:10
#define assert(...)
Forwards to assert_#args. See assert_1(), assert_2().
Definition: Debug.h:24
const T * ptr() const
Definition: Optional.h:184
optional & operator=(const optional &rhs)
Assign wrapped object.
Definition: Optional.h:158
optional & operator=(optional< U > &&rhs)
Definition: Optional.h:78
Enables any type to be optional so it can exist in an uninitialized null state.
Definition: Optional.h:52
optional & operator=(optional< U > &rhs)
Definition: Optional.h:162
T * ptr()
Definition: Optional.h:106
const T & operator*() const
Definition: Optional.h:89
optional(U &&rhs)
Definition: Optional.h:145
bool operator!=(optnull_t) const
Definition: Optional.h:87
optional & operator=(const optional &rhs)
Assign wrapped object.
Definition: Optional.h:73
optional & operator=(const optional< U > &rhs)
Definition: Optional.h:76
optional(optional< U > &&rhs)
Definition: Optional.h:144
bool operator==(const String &lhs, const String &rhs)
Definition: String.h:139
const T & operator*() const
Definition: Optional.h:171
optional(optnull_t)
Definition: Optional.h:138
T * ptr()
Definition: Optional.h:185
optional & operator=(U &&rhs)
Assign object. Reference must be bound to an object before being assigned, this is asserted at runtim...
Definition: Optional.h:166
optional(optional &&rhs)
Definition: Optional.h:141
optional & operator=(optional &rhs)
Definition: Optional.h:74
T & operator*()
Definition: Optional.h:90
optional(optional &&rhs)
Definition: Optional.h:61
bool operator==(optnull_t) const
Definition: Optional.h:168
optional(T *rhs)
Definition: Optional.h:137
optional & operator=(const optional< U > &rhs)
Definition: Optional.h:161
Global Honeycomb namespace.
optional(optional< U > &&rhs)
Definition: Optional.h:64