mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-16 16:37:08 +00:00
Result: Add default template for Result<T, E>
It currently is a tagged pair instead of a tagged union because it was much easier to write and the optimization can come later. BUG=dawn:19 Change-Id: Idbfd86d559655b38871c2d1768bdd758e797dfbd Reviewed-on: https://dawn-review.googlesource.com/c/2701 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Stephen White <senorblanco@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
813bfbd061
commit
df72914a60
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
// Result<T, E> is the following sum type (Haskell notation):
|
||||
//
|
||||
@@ -124,6 +125,38 @@ class DAWN_NO_DISCARD Result<T*, E*> {
|
||||
intptr_t mPayload = kEmptyPayload;
|
||||
};
|
||||
|
||||
// Catchall definition of Result<T, E> implemented as a tagged struct. It could be improved to use
|
||||
// a tagged union instead if it turns out to be a hotspot. T and E must be movable and default
|
||||
// constructible.
|
||||
template <typename T, typename E>
|
||||
class DAWN_NO_DISCARD Result {
|
||||
public:
|
||||
Result(T&& success);
|
||||
Result(E&& error);
|
||||
|
||||
Result(Result<T, E>&& other);
|
||||
Result<T, E>& operator=(Result<T, E>&& other);
|
||||
|
||||
~Result();
|
||||
|
||||
bool IsError() const;
|
||||
bool IsSuccess() const;
|
||||
|
||||
T&& AcquireSuccess();
|
||||
E&& AcquireError();
|
||||
|
||||
private:
|
||||
enum PayloadType {
|
||||
Success = 0,
|
||||
Error = 1,
|
||||
Acquired = 2,
|
||||
};
|
||||
PayloadType mType;
|
||||
|
||||
E mError;
|
||||
T mSuccess;
|
||||
};
|
||||
|
||||
// Implementation of Result<void, E*>
|
||||
template <typename E>
|
||||
Result<void, E*>::Result() {
|
||||
@@ -247,4 +280,56 @@ E* Result<T*, E*>::GetErrorFromPayload(intptr_t payload) {
|
||||
return reinterpret_cast<E*>(payload ^ 1);
|
||||
}
|
||||
|
||||
// Implementation of Result<T, E>
|
||||
template <typename T, typename E>
|
||||
Result<T, E>::Result(T&& success) : mType(Success), mSuccess(success) {
|
||||
}
|
||||
|
||||
template <typename T, typename E>
|
||||
Result<T, E>::Result(E&& error) : mType(Error), mError(error) {
|
||||
}
|
||||
|
||||
template <typename T, typename E>
|
||||
Result<T, E>::~Result() {
|
||||
ASSERT(mType == Acquired);
|
||||
}
|
||||
|
||||
template <typename T, typename E>
|
||||
Result<T, E>::Result(Result<T, E>&& other)
|
||||
: mType(other.mType), mError(std::move(other.mError)), mSuccess(other.mSuccess) {
|
||||
other.mType = Acquired;
|
||||
}
|
||||
template <typename T, typename E>
|
||||
Result<T, E>& Result<T, E>::operator=(Result<T, E>&& other) {
|
||||
mType = other.mType;
|
||||
mError = std::move(other.mError);
|
||||
mSuccess = std::move(other.mSuccess);
|
||||
other.mType = Acquired;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, typename E>
|
||||
bool Result<T, E>::IsError() const {
|
||||
return mType == Error;
|
||||
}
|
||||
|
||||
template <typename T, typename E>
|
||||
bool Result<T, E>::IsSuccess() const {
|
||||
return mType == Success;
|
||||
}
|
||||
|
||||
template <typename T, typename E>
|
||||
T&& Result<T, E>::AcquireSuccess() {
|
||||
ASSERT(mType == Success);
|
||||
mType = Acquired;
|
||||
return std::move(mSuccess);
|
||||
}
|
||||
|
||||
template <typename T, typename E>
|
||||
E&& Result<T, E>::AcquireError() {
|
||||
ASSERT(mType == Error);
|
||||
mType = Acquired;
|
||||
return std::move(mError);
|
||||
}
|
||||
|
||||
#endif // COMMON_RESULT_H_
|
||||
|
||||
Reference in New Issue
Block a user