diff options
author | David Blaikie <dblaikie@gmail.com> | 2013-02-20 00:26:04 +0000 |
---|---|---|
committer | David Blaikie <dblaikie@gmail.com> | 2013-02-20 00:26:04 +0000 |
commit | a28eda7e401f37a2fe42ca9bba96b6e662b60cf0 (patch) | |
tree | 3280d2d2f26755931bfe557d97034f8a16b1b3a8 /include/llvm/ADT | |
parent | 9bc2c994827f2ff881d0563f0c14134b794b4928 (diff) | |
download | external_llvm-a28eda7e401f37a2fe42ca9bba96b6e662b60cf0.zip external_llvm-a28eda7e401f37a2fe42ca9bba96b6e662b60cf0.tar.gz external_llvm-a28eda7e401f37a2fe42ca9bba96b6e662b60cf0.tar.bz2 |
Allow llvm::Optional to work with types without default constructors.
This generalizes Optional to require less from the T type by using aligned
storage for backing & placement new/deleting the T into it when necessary.
Also includes unit tests.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175580 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/ADT')
-rw-r--r-- | include/llvm/ADT/Optional.h | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 6f58ffa..cc6065c 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -17,6 +17,7 @@ #define LLVM_ADT_OPTIONAL_H #include "llvm/Support/Compiler.h" +#include "llvm/Support/AlignOf.h" #include <cassert> #if LLVM_HAS_RVALUE_REFERENCES @@ -27,14 +28,22 @@ namespace llvm { template<typename T> class Optional { - T x; + AlignedCharArrayUnion<T> storage; bool hasVal; public: - explicit Optional() : x(), hasVal(false) {} - Optional(const T &y) : x(y), hasVal(true) {} + explicit Optional() : hasVal(false) {} + Optional(const T &y) : hasVal(true) { + new (storage.buffer) T(y); + } + Optional(const Optional &O) : hasVal(O.hasVal) { + if (hasVal) + new (storage.buffer) T(*O); + } #if LLVM_HAS_RVALUE_REFERENCES - Optional(T &&y) : x(std::forward<T>(y)), hasVal(true) {} + Optional(T &&y) : hasVal(true) { + new (storage.buffer) T(std::forward<T>(y)); + } #endif static inline Optional create(const T* y) { @@ -42,22 +51,49 @@ public: } Optional &operator=(const T &y) { - x = y; - hasVal = true; + if (hasVal) + **this = y; + else { + new (storage.buffer) T(y); + hasVal = true; + } + return *this; + } + + Optional &operator=(const Optional &O) { + if (!O) + Reset(); + else + *this = *O; return *this; } + + void Reset() { + if (hasVal) { + (*this)->~T(); + hasVal = false; + } + } + + ~Optional() { + Reset(); + } - const T* getPointer() const { assert(hasVal); return &x; } - const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return x; } + const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); } + T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); } + const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } + T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } operator bool() const { return hasVal; } bool hasValue() const { return hasVal; } const T* operator->() const { return getPointer(); } - const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return x; } + T* operator->() { return getPointer(); } + const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } + T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } #if LLVM_HAS_RVALUE_REFERENCE_THIS - T&& getValue() && { assert(hasVal); return std::move(x); } - T&& operator*() && { assert(hasVal); return std::move(x); } + T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } + T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } #endif }; |