llvm.org GIT mirror llvm / 89f1989
Revert rL317019, "[ADT] Split optional to only include copy mechanics and dtor for non-trivial types." Seems g++-4.8 (eg. Ubuntu 14.04) doesn't like this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317077 91177308-0d34-0410-b5e6-96231b3b80d8 NAKAMURA Takumi 1 year, 9 months ago
2 changed file(s) with 63 addition(s) and 122 deletion(s). Raw diff Collapse all Expand all
2626
2727 namespace llvm {
2828
29 namespace optional_detail {
30 /// Storage for any type.
31 template struct OptionalStorage {
29 template
30 class Optional {
3231 AlignedCharArrayUnion storage;
3332 bool hasVal = false;
3433
35 OptionalStorage() = default;
36
37 OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
38 OptionalStorage(const OptionalStorage &O) : hasVal(O.hasVal) {
34 public:
35 using value_type = T;
36
37 Optional(NoneType) {}
38 explicit Optional() {}
39
40 Optional(const T &y) : hasVal(true) {
41 new (storage.buffer) T(y);
42 }
43
44 Optional(const Optional &O) : hasVal(O.hasVal) {
3945 if (hasVal)
40 new (storage.buffer) T(*O.getPointer());
41 }
42 OptionalStorage(T &&y) : hasVal(true) {
46 new (storage.buffer) T(*O);
47 }
48
49 Optional(T &&y) : hasVal(true) {
4350 new (storage.buffer) T(std::forward(y));
4451 }
45 OptionalStorage(OptionalStorage &&O) : hasVal(O.hasVal) {
46 if (O.hasVal) {
47 new (storage.buffer) T(std::move(*O.getPointer()));
52
53 Optional(Optional &&O) : hasVal(O) {
54 if (O) {
55 new (storage.buffer) T(std::move(*O));
4856 O.reset();
4957 }
5058 }
5159
52 OptionalStorage &operator=(T &&y) {
60 ~Optional() {
61 reset();
62 }
63
64 Optional &operator=(T &&y) {
5365 if (hasVal)
54 *getPointer() = std::move(y);
66 **this = std::move(y);
5567 else {
5668 new (storage.buffer) T(std::move(y));
5769 hasVal = true;
5870 }
5971 return *this;
6072 }
61 OptionalStorage &operator=(OptionalStorage &&O) {
62 if (!O.hasVal)
73
74 Optional &operator=(Optional &&O) {
75 if (!O)
6376 reset();
6477 else {
65 *this = std::move(*O.getPointer());
78 *this = std::move(*O);
6679 O.reset();
6780 }
6881 return *this;
82 }
83
84 /// Create a new object by constructing it in place with the given arguments.
85 template
86 void emplace(ArgTypes &&...Args) {
87 reset();
88 hasVal = true;
89 new (storage.buffer) T(std::forward(Args)...);
90 }
91
92 static inline Optional create(const T* y) {
93 return y ? Optional(*y) : Optional();
6994 }
7095
7196 // FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
7398 // with the rvalue versions above - but this could place a different set of
7499 // requirements (notably: the existence of a default ctor) when implemented
75100 // in that way. Careful SFINAE to avoid such pitfalls would be required.
76 OptionalStorage &operator=(const T &y) {
101 Optional &operator=(const T &y) {
77102 if (hasVal)
78 *getPointer() = y;
103 **this = y;
79104 else {
80105 new (storage.buffer) T(y);
81106 hasVal = true;
82107 }
83108 return *this;
84109 }
85 OptionalStorage &operator=(const OptionalStorage &O) {
86 if (!O.hasVal)
110
111 Optional &operator=(const Optional &O) {
112 if (!O)
87113 reset();
88114 else
89 *this = *O.getPointer();
90 return *this;
91 }
92
93 ~OptionalStorage() { reset(); }
115 *this = *O;
116 return *this;
117 }
94118
95119 void reset() {
96120 if (hasVal) {
97 (*getPointer()).~T();
121 (**this).~T();
98122 hasVal = false;
99123 }
100124 }
101125
102 T *getPointer() {
103 assert(hasVal);
104 return reinterpret_cast(storage.buffer);
105 }
106 const T *getPointer() const {
107 assert(hasVal);
108 return reinterpret_cast(storage.buffer);
109 }
110 };
111
112 /// Storage for trivially copyable types only.
113 template struct OptionalStorage {
114 AlignedCharArrayUnion storage;
115 bool hasVal = false;
116
117 OptionalStorage() = default;
118
119 OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
120 OptionalStorage &operator=(const T &y) {
121 new (storage.buffer) T(y);
122 hasVal = true;
123 return *this;
124 }
125
126 void reset() { hasVal = false; }
127 };
128 } // namespace optional_detail
129
130 template class Optional {
131 optional_detail::OptionalStorage::value> Storage;
132
133 public:
134 using value_type = T;
135
136 constexpr Optional() {}
137 constexpr Optional(NoneType) {}
138
139 Optional(const T &y) : Storage(y) {}
140 Optional(const Optional &O) = default;
141
142 Optional(T &&y) : Storage(std::forward(y)) {}
143 Optional(Optional &&O) = default;
144
145 Optional &operator=(T &&y) {
146 Storage = std::move(y);
147 return *this;
148 }
149 Optional &operator=(Optional &&O) = default;
150
151 /// Create a new object by constructing it in place with the given arguments.
152 template void emplace(ArgTypes &&... Args) {
153 reset();
154 Storage.hasVal = true;
155 new (getPointer()) T(std::forward(Args)...);
156 }
157
158 static inline Optional create(const T *y) {
159 return y ? Optional(*y) : Optional();
160 }
161
162 Optional &operator=(const T &y) {
163 Storage = y;
164 return *this;
165 }
166 Optional &operator=(const Optional &O) = default;
167
168 void reset() { Storage.reset(); }
169
170 const T *getPointer() const {
171 assert(Storage.hasVal);
172 return reinterpret_cast(Storage.storage.buffer);
173 }
174 T *getPointer() {
175 assert(Storage.hasVal);
176 return reinterpret_cast(Storage.storage.buffer);
177 }
178 const T &getValue() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
179 T &getValue() LLVM_LVALUE_FUNCTION { return *getPointer(); }
180
181 explicit operator bool() const { return Storage.hasVal; }
182 bool hasValue() const { return Storage.hasVal; }
126 const T* getPointer() const { assert(hasVal); return reinterpret_cast(storage.buffer); }
127 T* getPointer() { assert(hasVal); return reinterpret_cast(storage.buffer); }
128 const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
129 T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
130
131 explicit operator bool() const { return hasVal; }
132 bool hasValue() const { return hasVal; }
183133 const T* operator->() const { return getPointer(); }
184134 T* operator->() { return getPointer(); }
185 const T &operator*() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
186 T &operator*() LLVM_LVALUE_FUNCTION { return *getPointer(); }
135 const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
136 T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
187137
188138 template
189139 constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
191141 }
192142
193143 #if LLVM_HAS_RVALUE_REFERENCE_THIS
194 T &&getValue() && { return std::move(*getPointer()); }
195 T &&operator*() && { return std::move(*getPointer()); }
144 T&& getValue() && { assert(hasVal); return std::move(*getPointer()); }
145 T&& operator*() && { assert(hasVal); return std::move(*getPointer()); }
196146
197147 template
198148 T getValueOr(U &&value) && {
517517 CheckRelation(InequalityLhs, InequalityRhs, !IsLess);
518518 }
519519
520 #if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \
521 (defined(__GNUC__) && __GNUC__ >= 5)
522 static_assert(std::is_trivially_copyable>::value,
523 "Should be trivially copyable");
524 static_assert(
525 !std::is_trivially_copyable>::value,
526 "Shouldn't be trivially copyable");
527 #endif
528
529520 } // end anonymous namespace
530521