mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
Revert [NFC] Better encapsulation of llvm::Optional Storage
llvm-svn: 354240
This commit is contained in:
parent
5c5814e83f
commit
d6568e2fdd
@ -29,89 +29,83 @@ namespace llvm {
|
|||||||
class raw_ostream;
|
class raw_ostream;
|
||||||
|
|
||||||
namespace optional_detail {
|
namespace optional_detail {
|
||||||
|
|
||||||
struct in_place_t {};
|
|
||||||
|
|
||||||
/// Storage for any type.
|
/// Storage for any type.
|
||||||
template <typename T, bool = is_trivially_copyable<T>::value>
|
template <typename T, bool = is_trivially_copyable<T>::value> struct OptionalStorage {
|
||||||
class OptionalStorage {
|
AlignedCharArrayUnion<T> storage;
|
||||||
union {
|
bool hasVal = false;
|
||||||
char empty;
|
|
||||||
T value;
|
OptionalStorage() = default;
|
||||||
};
|
|
||||||
bool hasVal;
|
OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
|
||||||
|
OptionalStorage(const OptionalStorage &O) : hasVal(O.hasVal) {
|
||||||
|
if (hasVal)
|
||||||
|
new (storage.buffer) T(*O.getPointer());
|
||||||
|
}
|
||||||
|
OptionalStorage(T &&y) : hasVal(true) {
|
||||||
|
new (storage.buffer) T(std::forward<T>(y));
|
||||||
|
}
|
||||||
|
OptionalStorage(OptionalStorage &&O) : hasVal(O.hasVal) {
|
||||||
|
if (O.hasVal) {
|
||||||
|
new (storage.buffer) T(std::move(*O.getPointer()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionalStorage &operator=(T &&y) {
|
||||||
|
if (hasVal)
|
||||||
|
*getPointer() = std::move(y);
|
||||||
|
else {
|
||||||
|
new (storage.buffer) T(std::move(y));
|
||||||
|
hasVal = true;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
OptionalStorage &operator=(OptionalStorage &&O) {
|
||||||
|
if (!O.hasVal)
|
||||||
|
reset();
|
||||||
|
else {
|
||||||
|
*this = std::move(*O.getPointer());
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
|
||||||
|
// could be made more efficient by passing by value, possibly unifying them
|
||||||
|
// with the rvalue versions above - but this could place a different set of
|
||||||
|
// requirements (notably: the existence of a default ctor) when implemented
|
||||||
|
// in that way. Careful SFINAE to avoid such pitfalls would be required.
|
||||||
|
OptionalStorage &operator=(const T &y) {
|
||||||
|
if (hasVal)
|
||||||
|
*getPointer() = y;
|
||||||
|
else {
|
||||||
|
new (storage.buffer) T(y);
|
||||||
|
hasVal = true;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
OptionalStorage &operator=(const OptionalStorage &O) {
|
||||||
|
if (!O.hasVal)
|
||||||
|
reset();
|
||||||
|
else
|
||||||
|
*this = *O.getPointer();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
~OptionalStorage() { reset(); }
|
~OptionalStorage() { reset(); }
|
||||||
|
|
||||||
OptionalStorage() noexcept : empty(), hasVal(false) {}
|
void reset() {
|
||||||
|
|
||||||
OptionalStorage(OptionalStorage const &other) : OptionalStorage() {
|
|
||||||
if (other.hasValue()) {
|
|
||||||
emplace(other.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OptionalStorage(OptionalStorage &&other) : OptionalStorage() {
|
|
||||||
if (other.hasValue()) {
|
|
||||||
emplace(std::move(other.value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Args>
|
|
||||||
explicit OptionalStorage(in_place_t, Args &&... args)
|
|
||||||
: value(std::forward<Args>(args)...), hasVal(true) {}
|
|
||||||
|
|
||||||
void reset() noexcept {
|
|
||||||
if (hasVal) {
|
if (hasVal) {
|
||||||
value.~T();
|
(*getPointer()).~T();
|
||||||
hasVal = false;
|
hasVal = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasValue() const noexcept { return hasVal; }
|
T *getPointer() {
|
||||||
|
|
||||||
T &getValue() LLVM_LVALUE_FUNCTION noexcept {
|
|
||||||
assert(hasVal);
|
assert(hasVal);
|
||||||
return value;
|
return reinterpret_cast<T *>(storage.buffer);
|
||||||
}
|
}
|
||||||
T const &getValue() const LLVM_LVALUE_FUNCTION noexcept {
|
const T *getPointer() const {
|
||||||
assert(hasVal);
|
assert(hasVal);
|
||||||
return value;
|
return reinterpret_cast<const T *>(storage.buffer);
|
||||||
}
|
|
||||||
#if LLVM_HAS_RVALUE_REFERENCE_THIS
|
|
||||||
T &&getValue() && noexcept {
|
|
||||||
assert(hasVal);
|
|
||||||
return std::move(value);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <class... Args> void emplace(Args &&... args) {
|
|
||||||
reset();
|
|
||||||
::new ((void *)std::addressof(value)) T(std::forward<Args>(args)...);
|
|
||||||
hasVal = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
OptionalStorage &operator=(T const &y) {
|
|
||||||
return (*this) = OptionalStorage(in_place_t{}, y);
|
|
||||||
}
|
|
||||||
OptionalStorage &operator=(T &&y) {
|
|
||||||
return (*this) = OptionalStorage(in_place_t{}, std::move(y));
|
|
||||||
}
|
|
||||||
|
|
||||||
OptionalStorage &operator=(OptionalStorage const &other) {
|
|
||||||
if (other.hasValue())
|
|
||||||
emplace(other.getValue());
|
|
||||||
else
|
|
||||||
reset();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
OptionalStorage &operator=(OptionalStorage &&other) {
|
|
||||||
if (other.hasValue())
|
|
||||||
emplace(std::move(other.getValue()));
|
|
||||||
else
|
|
||||||
reset();
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -126,10 +120,10 @@ public:
|
|||||||
constexpr Optional() {}
|
constexpr Optional() {}
|
||||||
constexpr Optional(NoneType) {}
|
constexpr Optional(NoneType) {}
|
||||||
|
|
||||||
Optional(const T &y) : Storage(optional_detail::in_place_t{}, y) {}
|
Optional(const T &y) : Storage(y) {}
|
||||||
Optional(const Optional &O) = default;
|
Optional(const Optional &O) = default;
|
||||||
|
|
||||||
Optional(T &&y) : Storage(optional_detail::in_place_t{}, std::move(y)) {}
|
Optional(T &&y) : Storage(std::forward<T>(y)) {}
|
||||||
Optional(Optional &&O) = default;
|
Optional(Optional &&O) = default;
|
||||||
|
|
||||||
Optional &operator=(T &&y) {
|
Optional &operator=(T &&y) {
|
||||||
@ -140,7 +134,9 @@ public:
|
|||||||
|
|
||||||
/// Create a new object by constructing it in place with the given arguments.
|
/// Create a new object by constructing it in place with the given arguments.
|
||||||
template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
|
template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
|
||||||
Storage.emplace(std::forward<ArgTypes>(Args)...);
|
reset();
|
||||||
|
Storage.hasVal = true;
|
||||||
|
new (getPointer()) T(std::forward<ArgTypes>(Args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Optional create(const T *y) {
|
static inline Optional create(const T *y) {
|
||||||
@ -155,17 +151,23 @@ public:
|
|||||||
|
|
||||||
void reset() { Storage.reset(); }
|
void reset() { Storage.reset(); }
|
||||||
|
|
||||||
const T *getPointer() const { return &Storage.getValue(); }
|
const T *getPointer() const {
|
||||||
T *getPointer() { return &Storage.getValue(); }
|
assert(Storage.hasVal);
|
||||||
const T &getValue() const LLVM_LVALUE_FUNCTION { return Storage.getValue(); }
|
return reinterpret_cast<const T *>(Storage.storage.buffer);
|
||||||
T &getValue() LLVM_LVALUE_FUNCTION { return Storage.getValue(); }
|
}
|
||||||
|
T *getPointer() {
|
||||||
|
assert(Storage.hasVal);
|
||||||
|
return reinterpret_cast<T *>(Storage.storage.buffer);
|
||||||
|
}
|
||||||
|
const T &getValue() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
|
||||||
|
T &getValue() LLVM_LVALUE_FUNCTION { return *getPointer(); }
|
||||||
|
|
||||||
explicit operator bool() const { return hasValue(); }
|
explicit operator bool() const { return Storage.hasVal; }
|
||||||
bool hasValue() const { return Storage.hasValue(); }
|
bool hasValue() const { return Storage.hasVal; }
|
||||||
const T *operator->() const { return getPointer(); }
|
const T *operator->() const { return getPointer(); }
|
||||||
T *operator->() { return getPointer(); }
|
T *operator->() { return getPointer(); }
|
||||||
const T &operator*() const LLVM_LVALUE_FUNCTION { return getValue(); }
|
const T &operator*() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
|
||||||
T &operator*() LLVM_LVALUE_FUNCTION { return getValue(); }
|
T &operator*() LLVM_LVALUE_FUNCTION { return *getPointer(); }
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
|
constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
|
||||||
@ -173,8 +175,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if LLVM_HAS_RVALUE_REFERENCE_THIS
|
#if LLVM_HAS_RVALUE_REFERENCE_THIS
|
||||||
T &&getValue() && { return std::move(Storage.getValue()); }
|
T &&getValue() && { return std::move(*getPointer()); }
|
||||||
T &&operator*() && { return std::move(Storage.getValue()); }
|
T &&operator*() && { return std::move(*getPointer()); }
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
T getValueOr(U &&value) && {
|
T getValueOr(U &&value) && {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user