|
@ -39,7 +39,7 @@ namespace gp{ |
|
|
new(buffer) T(gp::move(value)); |
|
|
new(buffer) T(gp::move(value)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
optional operator=(nullopt_t) { |
|
|
|
|
|
|
|
|
optional& operator=(nullopt_t) { |
|
|
if(ready) { |
|
|
if(ready) { |
|
|
((T*)buffer)->~T(); |
|
|
((T*)buffer)->~T(); |
|
|
ready = false; |
|
|
ready = false; |
|
@ -47,7 +47,7 @@ namespace gp{ |
|
|
return *this; |
|
|
return *this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
optional operator=(T& value) { |
|
|
|
|
|
|
|
|
optional& operator=(T& value) { |
|
|
if(ready) { |
|
|
if(ready) { |
|
|
*(T*)buffer = value; |
|
|
*(T*)buffer = value; |
|
|
} else { |
|
|
} else { |
|
@ -57,7 +57,7 @@ namespace gp{ |
|
|
return *this; |
|
|
return *this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
optional operator=(T&& value) { |
|
|
|
|
|
|
|
|
optional& operator=(T&& value) { |
|
|
if(ready) { |
|
|
if(ready) { |
|
|
*(T*)buffer = gp::move(value); |
|
|
*(T*)buffer = gp::move(value); |
|
|
} else { |
|
|
} else { |
|
@ -92,7 +92,7 @@ namespace gp{ |
|
|
template<typename T> |
|
|
template<typename T> |
|
|
class optional<T,false>{ |
|
|
class optional<T,false>{ |
|
|
bool ready = false; |
|
|
bool ready = false; |
|
|
kt">void* ptr; |
|
|
|
|
|
|
|
|
n">T* ptr; |
|
|
public: |
|
|
public: |
|
|
constexpr optional() |
|
|
constexpr optional() |
|
|
: ready{false} |
|
|
: ready{false} |
|
@ -102,50 +102,92 @@ namespace gp{ |
|
|
: ready{false} |
|
|
: ready{false} |
|
|
{} |
|
|
{} |
|
|
|
|
|
|
|
|
c1">// TODO: Add typesafe generic assignment
|
|
|
|
|
|
constexpr optional(T& value) |
|
|
|
|
|
|
|
|
k">template<typename U> |
|
|
|
|
|
constexpr optional(U& value) |
|
|
: ready{true} |
|
|
: ready{true} |
|
|
{ |
|
|
{ |
|
|
ptr = p">(void*)new T(value); // TODO: Use allocators
|
|
|
|
|
|
|
|
|
ptr = k">new U(value); // TODO: Use allocators
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
c1">// TODO: Add typesafe generic assignment
|
|
|
|
|
|
constexpr optional(T&& value) |
|
|
|
|
|
|
|
|
k">template<typename U> |
|
|
|
|
|
constexpr optional(U&& value) |
|
|
: ready{true} |
|
|
: ready{true} |
|
|
{ |
|
|
{ |
|
|
ptr = p">(void*)new T(gp::move(value)); // TODO: Use allocators
|
|
|
|
|
|
|
|
|
ptr = k">new U(gp::move(value)); // TODO: Use allocators
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
optional operator=(nullopt_t) { |
|
|
|
|
|
|
|
|
optional& operator=(nullopt_t) { |
|
|
if(ready) { |
|
|
if(ready) { |
|
|
delete p">(T*)ptr; |
|
|
|
|
|
|
|
|
delete ptr; |
|
|
ready = false; |
|
|
ready = false; |
|
|
} |
|
|
} |
|
|
return *this; |
|
|
return *this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
c1">// TODO: Add typesafe generic assignment
|
|
|
|
|
|
optional operator=(T& value) { |
|
|
|
|
|
|
|
|
k">template<typename U> |
|
|
|
|
|
optional& operator=(U& value) { |
|
|
if(ready) { |
|
|
if(ready) { |
|
|
*(T*)ptr = value; |
|
|
|
|
|
|
|
|
if constexpr (std::is_same_v<T, U>) { |
|
|
|
|
|
*ptr = value; |
|
|
|
|
|
} else { |
|
|
|
|
|
delete ptr; // TODO: Use allocators
|
|
|
|
|
|
ptr = new U(value); // TODO: Use allocators
|
|
|
|
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
ready = true; |
|
|
ready = true; |
|
|
ptr = (void*)new T(value); // TODO: Use allocators
|
|
|
|
|
|
|
|
|
ptr = k">new U(value); // TODO: Use allocators
|
|
|
} |
|
|
} |
|
|
return *this; |
|
|
return *this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
c1">// TODO: Add typesafe generic assignment
|
|
|
|
|
|
optional operator=(T&& value) { |
|
|
|
|
|
|
|
|
k">template<typename U> |
|
|
|
|
|
optional& operator=(U&& value) { |
|
|
if(ready) { |
|
|
if(ready) { |
|
|
*(T*)ptr = gp::move(value); |
|
|
|
|
|
|
|
|
if constexpr (std::is_same_v<T, U>) { |
|
|
|
|
|
*ptr = gp::move(value); |
|
|
|
|
|
} else { |
|
|
|
|
|
delete ptr; // TODO: Use allocators
|
|
|
|
|
|
ptr = new U(gp::move(value)); // TODO: Use allocators
|
|
|
|
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
ready = true; |
|
|
ready = true; |
|
|
ptr = (void*)new T(gp::move(value)); // TODO: Use allocators
|
|
|
|
|
|
|
|
|
ptr = k">new U(gp::move(value)); // TODO: Use allocators
|
|
|
} |
|
|
} |
|
|
return *this; |
|
|
return *this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<> |
|
|
|
|
|
optional& operator=<optional>(optional& value) { |
|
|
|
|
|
if(ready) { |
|
|
|
|
|
*ptr = value; |
|
|
|
|
|
} else { |
|
|
|
|
|
ready = true; |
|
|
|
|
|
ptr = new optional(value.value()); // TODO: Use allocators
|
|
|
|
|
|
} |
|
|
|
|
|
return *this; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<> |
|
|
|
|
|
optional& operator=<optional>(optional&& value){ |
|
|
|
|
|
if(ready) { |
|
|
|
|
|
delete ptr; // TODO: Use allocators
|
|
|
|
|
|
} |
|
|
|
|
|
if(value.ready) { |
|
|
|
|
|
ptr = value.ptr; |
|
|
|
|
|
value.ready = false; |
|
|
|
|
|
ready = true; |
|
|
|
|
|
return *this; |
|
|
|
|
|
} else { |
|
|
|
|
|
ready = false; |
|
|
|
|
|
return *this; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
operator T&() { |
|
|
|
|
|
gp_config::assertion(ready, "bad optional access"); |
|
|
|
|
|
return *ptr; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
constexpr bool has_value() |
|
|
constexpr bool has_value() |
|
|
{ |
|
|
{ |
|
|
return ready; |
|
|
return ready; |
|
@ -162,7 +204,13 @@ namespace gp{ |
|
|
} else { |
|
|
} else { |
|
|
gp_config::assertion(ready, "bad optional access"); |
|
|
gp_config::assertion(ready, "bad optional access"); |
|
|
} |
|
|
} |
|
|
return *reinterpret_cast<T*>(ptr); |
|
|
|
|
|
|
|
|
return *ptr; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
~optional() { |
|
|
|
|
|
if(ready) { |
|
|
|
|
|
delete ptr; // TODO: Use allocators
|
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
} |
|
|
} |