api: Allow v8::Maybe<MovableType>.

Change-Id: I29bcdf3302f37568e8c8925e70a01ba342c17925
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3606229
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Anton Bikineev <bikineev@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80288}
This commit is contained in:
Anton Bikineev 2022-04-28 20:31:24 +02:00 committed by V8 LUCI CQ
parent 896f6e749a
commit 2655d3d18d
3 changed files with 67 additions and 1 deletions

View File

@ -5,6 +5,9 @@
#ifndef INCLUDE_V8_MAYBE_H_
#define INCLUDE_V8_MAYBE_H_
#include <type_traits>
#include <utility>
#include "v8-internal.h" // NOLINT(build/include_directory)
#include "v8config.h" // NOLINT(build/include_directory)
@ -57,11 +60,20 @@ class Maybe {
* Converts this Maybe<> to a value of type T. If this Maybe<> is
* nothing (empty), V8 will crash the process.
*/
V8_INLINE T FromJust() const {
V8_INLINE T FromJust() const& {
if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
return value_;
}
/**
* Converts this Maybe<> to a value of type T. If this Maybe<> is
* nothing (empty), V8 will crash the process.
*/
V8_INLINE T FromJust() && {
if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
return std::move(value_);
}
/**
* Converts this Maybe<> to a value of type T, using a default value if this
* Maybe<> is nothing (empty).
@ -82,6 +94,7 @@ class Maybe {
private:
Maybe() : has_value_(false) {}
explicit Maybe(const T& t) : has_value_(true), value_(t) {}
explicit Maybe(T&& t) : has_value_(true), value_(std::move(t)) {}
bool has_value_;
T value_;
@ -90,6 +103,8 @@ class Maybe {
friend Maybe<U> Nothing();
template <class U>
friend Maybe<U> Just(const U& u);
template <class U, std::enable_if_t<!std::is_lvalue_reference_v<U>>*>
friend Maybe<U> Just(U&& u);
};
template <class T>
@ -102,6 +117,14 @@ inline Maybe<T> Just(const T& t) {
return Maybe<T>(t);
}
// Don't use forwarding references here but instead use two overloads.
// Forwarding references only work when type deduction takes place, which is not
// the case for callsites such as Just<Type>(t).
template <class T, std::enable_if_t<!std::is_lvalue_reference_v<T>>* = nullptr>
inline Maybe<T> Just(T&& t) {
return Maybe<T>(std::move(t));
}
// A template specialization of Maybe<T> for the case of T = void.
template <>
class Maybe<void> {

View File

@ -216,6 +216,7 @@ v8_source_set("unittests_sources") {
"api/isolate-unittest.cc",
"api/remote-object-unittest.cc",
"api/resource-constraints-unittest.cc",
"api/v8-maybe-unittest.cc",
"api/v8-object-unittest.cc",
"base/address-region-unittest.cc",
"base/atomic-utils-unittest.cc",

View File

@ -0,0 +1,42 @@
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/v8-maybe.h"
#include "src/base/compiler-specific.h"
#include "src/base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
namespace {
struct Movable {
Movable() = default;
Movable(const Movable&) = delete;
Movable& operator=(const Movable&) = delete;
Movable(Movable&&) V8_NOEXCEPT = default;
Movable& operator=(Movable&&) V8_NOEXCEPT = default;
};
} // namespace
TEST(MaybeTest, AllowMovableTypes) {
Maybe<Movable> m1 = Just(Movable{});
EXPECT_TRUE(m1.IsJust());
Maybe<Movable> m2 = Just<Movable>({});
EXPECT_TRUE(m2.IsJust());
Maybe<Movable> m3 = Nothing<Movable>();
EXPECT_TRUE(m3.IsNothing());
Maybe<Movable> m4 = Just(Movable{});
Movable mm = std::move(m4).FromJust();
USE(mm);
}
} // namespace internal
} // namespace v8