Allow ResultOrError to downcast from backend to frontend types
More concretely this makes Result<T*, E*> able to be move-constructed from Result<ChildClassOfT*, E*> for free. BUG=dawn:19 Change-Id: Iea2b8997079ac3bfcf270d6b73a79cf5cac2c06f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/11860 Reviewed-by: Austin Eng <enga@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
5f53d5302f
commit
bd481fc199
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
// Result<T, E> is the following sum type (Haskell notation):
|
// Result<T, E> is the following sum type (Haskell notation):
|
||||||
|
@ -117,8 +118,11 @@ class DAWN_NO_DISCARD Result<T*, E*> {
|
||||||
Result(T* success);
|
Result(T* success);
|
||||||
Result(E* error);
|
Result(E* error);
|
||||||
|
|
||||||
Result(Result<T*, E*>&& other);
|
// Support returning a Result<T*, E*> from a Result<TChild*, E*>
|
||||||
Result<T*, E*>& operator=(Result<T*, E>&& other);
|
template <typename TChild>
|
||||||
|
Result(Result<TChild*, E*>&& other);
|
||||||
|
template <typename TChild>
|
||||||
|
Result<T*, E*>& operator=(Result<TChild*, E>&& other);
|
||||||
|
|
||||||
~Result();
|
~Result();
|
||||||
|
|
||||||
|
@ -129,6 +133,9 @@ class DAWN_NO_DISCARD Result<T*, E*> {
|
||||||
E* AcquireError();
|
E* AcquireError();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template <typename T2, typename E2>
|
||||||
|
friend class Result;
|
||||||
|
|
||||||
intptr_t mPayload = detail::kEmptyPayload;
|
intptr_t mPayload = detail::kEmptyPayload;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -265,13 +272,17 @@ Result<T*, E*>::Result(E* error) : mPayload(detail::MakePayload(error, detail::E
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename E>
|
template <typename T, typename E>
|
||||||
Result<T*, E*>::Result(Result<T*, E*>&& other) : mPayload(other.mPayload) {
|
template <typename TChild>
|
||||||
|
Result<T*, E*>::Result(Result<TChild*, E*>&& other) : mPayload(other.mPayload) {
|
||||||
other.mPayload = detail::kEmptyPayload;
|
other.mPayload = detail::kEmptyPayload;
|
||||||
|
static_assert(std::is_same<T, TChild>::value || std::is_base_of<T, TChild>::value, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename E>
|
template <typename T, typename E>
|
||||||
Result<T*, E*>& Result<T*, E*>::operator=(Result<T*, E>&& other) {
|
template <typename TChild>
|
||||||
|
Result<T*, E*>& Result<T*, E*>::operator=(Result<TChild*, E>&& other) {
|
||||||
ASSERT(mPayload == detail::kEmptyPayload);
|
ASSERT(mPayload == detail::kEmptyPayload);
|
||||||
|
static_assert(std::is_same<T, TChild>::value || std::is_base_of<T, TChild>::value, "");
|
||||||
mPayload = other.mPayload;
|
mPayload = other.mPayload;
|
||||||
other.mPayload = detail::kEmptyPayload;
|
other.mPayload = detail::kEmptyPayload;
|
||||||
return *this;
|
return *this;
|
||||||
|
|
|
@ -139,6 +139,31 @@ TEST(ResultBothPointer, ReturningSuccess) {
|
||||||
TestSuccess(&result, &dummySuccess);
|
TestSuccess(&result, &dummySuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests converting from a Result<TChild*, E*>
|
||||||
|
TEST(ResultBothPointer, ConversionFromChildClass) {
|
||||||
|
struct T {
|
||||||
|
int a;
|
||||||
|
};
|
||||||
|
struct TChild : T {};
|
||||||
|
|
||||||
|
TChild child;
|
||||||
|
T* childAsT = &child;
|
||||||
|
{
|
||||||
|
Result<T*, int*> result(&child);
|
||||||
|
TestSuccess(&result, childAsT);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Result<TChild*, int*> resultChild(&child);
|
||||||
|
Result<T*, int*> result(std::move(resultChild));
|
||||||
|
TestSuccess(&result, childAsT);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Result<TChild*, int*> resultChild(&child);
|
||||||
|
Result<T*, int*> result = std::move(resultChild);
|
||||||
|
TestSuccess(&result, childAsT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Result<const T*, E*>
|
// Result<const T*, E*>
|
||||||
|
|
||||||
// Test constructing an error Result<const T*, E*>
|
// Test constructing an error Result<const T*, E*>
|
||||||
|
|
Loading…
Reference in New Issue