add value_or to optional

Add full compliment of operator*, have them assert in debug,
but not throw in release as per c++ spec.

Add full compliment of value() have them crash if there is
no value as per the c++ spec.

Add value_or.

Add test for value_or.

Change-Id: Ib0d9a01fba367768e66d00fbc61b471397e8582c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/425476
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
Herb Derby 2021-07-07 17:43:57 -04:00 committed by Skia Commit-Bot
parent 6ca0536bd5
commit d390c642ac
2 changed files with 63 additions and 12 deletions

View File

@ -118,32 +118,62 @@ public:
return *this;
}
const T& value() const {
T& operator*() & {
SkASSERT(fHasValue);
return fPayload.fValue;
}
T& value() {
const T& operator*() const& {
SkASSERT(fHasValue);
return fPayload.fValue;
}
T& operator*() {
T&& operator*() && {
SkASSERT(fHasValue);
return this->value();
return std::move(fPayload.fValue);
}
const T&& operator*() const&& {
SkASSERT(fHasValue);
return std::move(fPayload.fValue);
}
const T& value() const& {
SkASSERT_RELEASE(fHasValue);
return **this;
}
T& value() & {
SkASSERT_RELEASE(fHasValue);
return **this;
}
const T&& value() const&& {
SkASSERT_RELEASE(fHasValue);
return std::move(**this);
}
T&& value() && {
SkASSERT_RELEASE(fHasValue);
return std::move(**this);
}
T* operator->() {
SkASSERT(fHasValue);
return &this->value();
}
const T& operator*() const {
return this->value();
return &**this;
}
const T* operator->() const {
SkASSERT(fHasValue);
return &this->value();
return &**this;
}
template<typename U>
T value_or(U&& value) const& {
return this->has_value() ? **this : static_cast<T>(std::forward<U>(value));
}
template<typename U>
T value_or(U&& value) && {
return this->has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(value));
}
bool has_value() const {

View File

@ -22,6 +22,27 @@ DEF_TEST(SkTOptionalNulloptCtor, r) {
REPORTER_ASSERT(r, !o.has_value());
}
DEF_TEST(SkTOptionalValueOr, r) {
{
skstd::optional<const char*> o;
REPORTER_ASSERT(r, !strcmp(o.value_or("Hello"), "Hello"));
}
{
skstd::optional<const char*> o("Bye");
REPORTER_ASSERT(r, !strcmp(o.value_or("Hello"), "Bye"));
}
{
skstd::optional<std::unique_ptr<int>> o;
std::unique_ptr<int> a = std::move(o).value_or(std::make_unique<int>(5));
REPORTER_ASSERT(r, *a == 5);
}
{
skstd::optional<std::unique_ptr<int>> o(std::make_unique<int>(3));
std::unique_ptr<int> a = std::move(o).value_or(std::make_unique<int>(5));
REPORTER_ASSERT(r, *a == 3);
}
}
DEF_TEST(SkTOptionalValue, r) {
skstd::optional<const char*> o("test");
REPORTER_ASSERT(r, o);