diff options
author | Minijackson <minijackson@riseup.net> | 2018-03-12 17:22:20 +0100 |
---|---|---|
committer | Minijackson <minijackson@riseup.net> | 2018-03-12 17:22:20 +0100 |
commit | 7f8d189705d621e1d040391add8709ad8d013f3d (patch) | |
tree | 9afc012f56694260b534e8af44ba5b5aa6a1ff21 | |
parent | 35aaeffc02e66aaef9641cd6e922510602130004 (diff) | |
download | kube-7f8d189705d621e1d040391add8709ad8d013f3d.tar.gz kube-7f8d189705d621e1d040391add8709ad8d013f3d.zip |
Hopefully fix the Copy constructor issue on OS Xexpected-copy-constr
-rw-r--r-- | framework/src/errors.h | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/framework/src/errors.h b/framework/src/errors.h index 4249cf8d..a0b27084 100644 --- a/framework/src/errors.h +++ b/framework/src/errors.h | |||
@@ -104,9 +104,13 @@ template <typename Error, typename Type> | |||
104 | struct StorageBase | 104 | struct StorageBase |
105 | { | 105 | { |
106 | protected: | 106 | protected: |
107 | // Rule of 5 {{{ | ||
108 | 107 | ||
109 | StorageBase(const StorageBase &other) : mIsValue(other.mIsValue) | 108 | // To be able to define a copy constructor in a child class |
109 | StorageBase() {} | ||
110 | |||
111 | // Rule of 5 (copy constructors defined in StorageCopyConstructor) {{{ | ||
112 | |||
113 | StorageBase(StorageBase &&other) : mIsValue(other.mIsValue) | ||
110 | { | 114 | { |
111 | // This is a constructor, you have to construct object, not assign them | 115 | // This is a constructor, you have to construct object, not assign them |
112 | // (hence the placement new) | 116 | // (hence the placement new) |
@@ -128,33 +132,12 @@ protected: | |||
128 | // And so, the placement new allows us to call the constructor of | 132 | // And so, the placement new allows us to call the constructor of |
129 | // `Type` or `Error` instead of its assignment operator. | 133 | // `Type` or `Error` instead of its assignment operator. |
130 | if (mIsValue) { | 134 | if (mIsValue) { |
131 | new (std::addressof(mValue)) Type(other.mValue); | ||
132 | } else { | ||
133 | new (std::addressof(mError)) Unexpected<Error>(other.mError); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | StorageBase(StorageBase &&other) : mIsValue(other.mIsValue) | ||
138 | { | ||
139 | // If you're thinking WTF, see the comment in the copy constructor above. | ||
140 | if (mIsValue) { | ||
141 | new (std::addressof(mValue)) Type(std::move(other.mValue)); | 135 | new (std::addressof(mValue)) Type(std::move(other.mValue)); |
142 | } else { | 136 | } else { |
143 | new (std::addressof(mError)) Unexpected<Error>(std::move(other.mError)); | 137 | new (std::addressof(mError)) Unexpected<Error>(std::move(other.mError)); |
144 | } | 138 | } |
145 | } | 139 | } |
146 | 140 | ||
147 | constexpr StorageBase &operator=(const StorageBase &other) | ||
148 | { | ||
149 | mIsValue = other.mIsValue; | ||
150 | if (mIsValue) { | ||
151 | mValue = other.mValue; | ||
152 | } else { | ||
153 | mError = other.mError; | ||
154 | } | ||
155 | return *this; | ||
156 | } | ||
157 | |||
158 | constexpr StorageBase &operator=(StorageBase &&other) | 141 | constexpr StorageBase &operator=(StorageBase &&other) |
159 | { | 142 | { |
160 | this->~StorageBase(); | 143 | this->~StorageBase(); |
@@ -215,13 +198,56 @@ protected: | |||
215 | bool mIsValue; | 198 | bool mIsValue; |
216 | }; | 199 | }; |
217 | 200 | ||
201 | // Struct used to add the copy constructor / assignment only if both types are copy constructible | ||
202 | template <typename Error, typename Type, | ||
203 | bool both_copy_constructible = std::is_copy_constructible<Error>::value &&std::is_copy_constructible<Type>::value> | ||
204 | struct StorageCopyConstructor; | ||
205 | |||
206 | template <typename Error, typename Type> | ||
207 | struct StorageCopyConstructor<Error, Type, true> : StorageBase<Error, Type> | ||
208 | { | ||
209 | protected: | ||
210 | using StorageBase<Error, Type>::StorageBase; | ||
211 | |||
212 | StorageCopyConstructor(const StorageCopyConstructor &other) : StorageBase<Error, Type>() | ||
213 | { | ||
214 | // If you're thinking WTF, see the comment in the move constructor above. | ||
215 | this->mIsValue = other.mIsValue; | ||
216 | if (this->mIsValue) { | ||
217 | new (std::addressof(this->mValue)) Type(other.mValue); | ||
218 | } else { | ||
219 | new (std::addressof(this->mError)) Unexpected<Error>(other.mError); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | StorageCopyConstructor &operator=(const StorageCopyConstructor &other) | ||
224 | { | ||
225 | this->mIsValue = other.mIsValue; | ||
226 | if (this->mIsValue) { | ||
227 | this->mValue = other.mValue; | ||
228 | } else { | ||
229 | this->mError = other.mError; | ||
230 | } | ||
231 | return *this; | ||
232 | } | ||
233 | |||
234 | }; | ||
235 | |||
236 | template <typename Error, typename Type> | ||
237 | struct StorageCopyConstructor<Error, Type, false> : StorageBase<Error, Type> | ||
238 | { | ||
239 | protected: | ||
240 | using StorageBase<Error, Type>::StorageBase; | ||
241 | }; | ||
242 | |||
243 | |||
218 | // Write functions here when storage related, whether Type is void or not | 244 | // Write functions here when storage related, whether Type is void or not |
219 | template <typename Error, typename Type> | 245 | template <typename Error, typename Type> |
220 | struct Storage : StorageBase<Error, Type> | 246 | struct Storage : StorageCopyConstructor<Error, Type> |
221 | { | 247 | { |
222 | protected: | 248 | protected: |
223 | // Forward the construction to StorageBase | 249 | // Forward the construction to StorageBase |
224 | using StorageBase<Error, Type>::StorageBase; | 250 | using StorageCopyConstructor<Error, Type>::StorageCopyConstructor; |
225 | }; | 251 | }; |
226 | 252 | ||
227 | // Write functions here when dev API related and when Type != void | 253 | // Write functions here when dev API related and when Type != void |
@@ -266,17 +292,17 @@ struct ExpectedBase : detail::Storage<Error, Type> | |||
266 | 292 | ||
267 | // Write functions here when dev API related and when Type == void | 293 | // Write functions here when dev API related and when Type == void |
268 | template <typename Error> | 294 | template <typename Error> |
269 | struct ExpectedBase<Error, void> : detail::Storage<Error, void> | 295 | struct ExpectedBase<Error, void> : Storage<Error, void> |
270 | { | 296 | { |
271 | // Rewrite constructors for unexpected because Expected doesn't have direct access to it. | 297 | // Rewrite constructors for unexpected because Expected doesn't have direct access to it. |
272 | template <typename OtherError> | 298 | template <typename OtherError> |
273 | constexpr ExpectedBase(const Unexpected<OtherError> &error) | 299 | constexpr ExpectedBase(const Unexpected<OtherError> &error) |
274 | : detail::Storage<Error, void>(detail::tags::Unexpected{}, error) | 300 | : Storage<Error, void>(tags::Unexpected{}, error) |
275 | { | 301 | { |
276 | } | 302 | } |
277 | template <typename OtherError> | 303 | template <typename OtherError> |
278 | constexpr ExpectedBase(Unexpected<OtherError> &&error) | 304 | constexpr ExpectedBase(Unexpected<OtherError> &&error) |
279 | : detail::Storage<Error, void>(detail::tags::Unexpected{}, std::move(error)) | 305 | : Storage<Error, void>(tags::Unexpected{}, std::move(error)) |
280 | { | 306 | { |
281 | } | 307 | } |
282 | }; | 308 | }; |