optional.h 30.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file is a clone of "base/optional.h" in chromium.
// Keep in sync, especially when fixing bugs.
// Copyright 2017 the V8 project authors. All rights reserved.

#ifndef V8_BASE_OPTIONAL_H_
#define V8_BASE_OPTIONAL_H_

#include <type_traits>
13
#include <utility>
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

#include "src/base/logging.h"

namespace v8 {
namespace base {

// Specification:
// http://en.cppreference.com/w/cpp/utility/optional/in_place_t
struct in_place_t {};

// Specification:
// http://en.cppreference.com/w/cpp/utility/optional/nullopt_t
struct nullopt_t {
  constexpr explicit nullopt_t(int) {}
};

// Specification:
// http://en.cppreference.com/w/cpp/utility/optional/in_place
constexpr in_place_t in_place = {};

// Specification:
// http://en.cppreference.com/w/cpp/utility/optional/nullopt
constexpr nullopt_t nullopt(0);

38 39 40 41
// Forward declaration, which is refered by following helpers.
template <typename T>
class Optional;

42 43 44
namespace internal {

template <typename T, bool = std::is_trivially_destructible<T>::value>
45
struct OptionalStorageBase {
46 47
  // Initializing |empty_| here instead of using default member initializing
  // to avoid errors in g++ 4.8.
48
  constexpr OptionalStorageBase() : empty_('\0') {}
49 50

  template <class... Args>
51 52
  constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
      : is_populated_(true), value_(std::forward<Args>(args)...) {}
53 54 55

  // When T is not trivially destructible we must call its
  // destructor before deallocating its memory.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
  // Note that this hides the (implicitly declared) move constructor, which
  // would be used for constexpr move constructor in OptionalStorage<T>.
  // It is needed iff T is trivially move constructible. However, the current
  // is_trivially_{copy,move}_constructible implementation requires
  // is_trivially_destructible (which looks a bug, cf:
  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 and
  // http://cplusplus.github.io/LWG/lwg-active.html#2116), so it is not
  // necessary for this case at the moment. Please see also the destructor
  // comment in "is_trivially_destructible = true" specialization below.
  ~OptionalStorageBase() {
    if (is_populated_) value_.~T();
  }

  template <class... Args>
  void Init(Args&&... args) {
    DCHECK(!is_populated_);
    ::new (&value_) T(std::forward<Args>(args)...);
    is_populated_ = true;
74 75
  }

76
  bool is_populated_ = false;
77 78 79 80 81 82 83 84 85 86
  union {
    // |empty_| exists so that the union will always be initialized, even when
    // it doesn't contain a value. Union members must be initialized for the
    // constructor to be 'constexpr'.
    char empty_;
    T value_;
  };
};

template <typename T>
87
struct OptionalStorageBase<T, true /* trivially destructible */> {
88 89
  // Initializing |empty_| here instead of using default member initializing
  // to avoid errors in g++ 4.8.
90
  constexpr OptionalStorageBase() : empty_('\0') {}
91 92

  template <class... Args>
93 94
  constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
      : is_populated_(true), value_(std::forward<Args>(args)...) {}
95 96

  // When T is trivially destructible (i.e. its destructor does nothing) there
97 98 99 100 101 102 103 104 105 106 107 108
  // is no need to call it. Implicitly defined destructor is trivial, because
  // both members (bool and union containing only variants which are trivially
  // destructible) are trivially destructible.
  // Explicitly-defaulted destructor is also trivial, but do not use it here,
  // because it hides the implicit move constructor. It is needed to implement
  // constexpr move constructor in OptionalStorage iff T is trivially move
  // constructible. Note that, if T is trivially move constructible, the move
  // constructor of OptionalStorageBase<T> is also implicitly defined and it is
  // trivially move constructor. If T is not trivially move constructible,
  // "not declaring move constructor without destructor declaration" here means
  // "delete move constructor", which works because any move constructor of
  // OptionalStorage will not refer to it in that case.
109

110 111 112 113 114 115 116 117
  template <class... Args>
  void Init(Args&&... args) {
    DCHECK(!is_populated_);
    ::new (&value_) T(std::forward<Args>(args)...);
    is_populated_ = true;
  }

  bool is_populated_ = false;
118 119 120 121 122 123 124 125 126
  union {
    // |empty_| exists so that the union will always be initialized, even when
    // it doesn't contain a value. Union members must be initialized for the
    // constructor to be 'constexpr'.
    char empty_;
    T value_;
  };
};

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
// Implement conditional constexpr copy and move constructors. These are
// constexpr if is_trivially_{copy,move}_constructible<T>::value is true
// respectively. If each is true, the corresponding constructor is defined as
// "= default;", which generates a constexpr constructor (In this case,
// the condition of constexpr-ness is satisfied because the base class also has
// compiler generated constexpr {copy,move} constructors). Note that
// placement-new is prohibited in constexpr.
#if defined(__GNUC__) && __GNUC__ < 5
// gcc <5 does not implement std::is_trivially_copy_constructible.
// Conservatively assume false for this configuration.
// TODO(clemensh): Remove this once we drop support for gcc <5.
#define TRIVIALLY_COPY_CONSTRUCTIBLE(T) false
#define TRIVIALLY_MOVE_CONSTRUCTIBLE(T) false
#else
#define TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
  std::is_trivially_copy_constructible<T>::value
#define TRIVIALLY_MOVE_CONSTRUCTIBLE(T) \
  std::is_trivially_move_constructible<T>::value
#endif
template <typename T, bool = TRIVIALLY_COPY_CONSTRUCTIBLE(T),
          bool = TRIVIALLY_MOVE_CONSTRUCTIBLE(T)>
#undef TRIVIALLY_COPY_CONSTRUCTIBLE
struct OptionalStorage : OptionalStorageBase<T> {
  // This is no trivially {copy,move} constructible case. Other cases are
  // defined below as specializations.

  // Accessing the members of template base class requires explicit
  // declaration.
  using OptionalStorageBase<T>::is_populated_;
  using OptionalStorageBase<T>::value_;
  using OptionalStorageBase<T>::Init;

  // Inherit constructors (specifically, the in_place constructor).
  using OptionalStorageBase<T>::OptionalStorageBase;

  // User defined constructor deletes the default constructor.
  // Define it explicitly.
  OptionalStorage() = default;

166
  OptionalStorage(const OptionalStorage& other) V8_NOEXCEPT {
167 168 169
    if (other.is_populated_) Init(other.value_);
  }

170
  OptionalStorage(OptionalStorage&& other) V8_NOEXCEPT {
171 172 173 174 175 176 177 178 179 180 181 182 183 184
    if (other.is_populated_) Init(std::move(other.value_));
  }
};

template <typename T>
struct OptionalStorage<T, true /* trivially copy constructible */,
                       false /* trivially move constructible */>
    : OptionalStorageBase<T> {
  using OptionalStorageBase<T>::is_populated_;
  using OptionalStorageBase<T>::value_;
  using OptionalStorageBase<T>::Init;
  using OptionalStorageBase<T>::OptionalStorageBase;

  OptionalStorage() = default;
185
  OptionalStorage(const OptionalStorage& other) V8_NOEXCEPT = default;
186

187
  OptionalStorage(OptionalStorage&& other) V8_NOEXCEPT {
188 189 190 191 192 193 194 195 196 197 198 199 200 201
    if (other.is_populated_) Init(std::move(other.value_));
  }
};

template <typename T>
struct OptionalStorage<T, false /* trivially copy constructible */,
                       true /* trivially move constructible */>
    : OptionalStorageBase<T> {
  using OptionalStorageBase<T>::is_populated_;
  using OptionalStorageBase<T>::value_;
  using OptionalStorageBase<T>::Init;
  using OptionalStorageBase<T>::OptionalStorageBase;

  OptionalStorage() = default;
202
  OptionalStorage(OptionalStorage&& other) V8_NOEXCEPT = default;
203

204
  OptionalStorage(const OptionalStorage& other) V8_NOEXCEPT {
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    if (other.is_populated_) Init(other.value_);
  }
};

template <typename T>
struct OptionalStorage<T, true /* trivially copy constructible */,
                       true /* trivially move constructible */>
    : OptionalStorageBase<T> {
  // If both trivially {copy,move} constructible are true, it is not necessary
  // to use user-defined constructors. So, just inheriting constructors
  // from the base class works.
  using OptionalStorageBase<T>::OptionalStorageBase;
};

// Base class to support conditionally usable copy-/move- constructors
// and assign operators.
template <typename T>
class OptionalBase {
  // This class provides implementation rather than public API, so everything
  // should be hidden. Often we use composition, but we cannot in this case
  // because of C++ language restriction.
 protected:
  constexpr OptionalBase() = default;
228 229
  constexpr OptionalBase(const OptionalBase& other) V8_NOEXCEPT = default;
  constexpr OptionalBase(OptionalBase&& other) V8_NOEXCEPT = default;
230 231 232 233 234 235 236

  template <class... Args>
  constexpr explicit OptionalBase(in_place_t, Args&&... args)
      : storage_(in_place, std::forward<Args>(args)...) {}

  // Implementation of converting constructors.
  template <typename U>
237
  explicit OptionalBase(const OptionalBase<U>& other) V8_NOEXCEPT {
238 239 240 241
    if (other.storage_.is_populated_) storage_.Init(other.storage_.value_);
  }

  template <typename U>
242
  explicit OptionalBase(OptionalBase<U>&& other) V8_NOEXCEPT {
243 244 245 246 247 248
    if (other.storage_.is_populated_)
      storage_.Init(std::move(other.storage_.value_));
  }

  ~OptionalBase() = default;

249
  OptionalBase& operator=(const OptionalBase& other) V8_NOEXCEPT {
250 251 252 253
    CopyAssign(other);
    return *this;
  }

254
  OptionalBase& operator=(OptionalBase&& other) V8_NOEXCEPT {
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
    MoveAssign(std::move(other));
    return *this;
  }

  template <typename U>
  void CopyAssign(const OptionalBase<U>& other) {
    if (other.storage_.is_populated_)
      InitOrAssign(other.storage_.value_);
    else
      FreeIfNeeded();
  }

  template <typename U>
  void MoveAssign(OptionalBase<U>&& other) {
    if (other.storage_.is_populated_)
      InitOrAssign(std::move(other.storage_.value_));
    else
      FreeIfNeeded();
  }

  template <typename U>
  void InitOrAssign(U&& value) {
    if (storage_.is_populated_)
      storage_.value_ = std::forward<U>(value);
    else
      storage_.Init(std::forward<U>(value));
  }

  void FreeIfNeeded() {
    if (!storage_.is_populated_) return;
    storage_.value_.~T();
    storage_.is_populated_ = false;
  }

  // For implementing conversion, allow access to other typed OptionalBase
  // class.
  template <typename U>
  friend class OptionalBase;

  OptionalStorage<T> storage_;
};

// The following {Copy,Move}{Constructible,Assignable} structs are helpers to
// implement constructor/assign-operator overloading. Specifically, if T is
// is not movable but copyable, Optional<T>'s move constructor should not
// participate in overload resolution. This inheritance trick implements that.
template <bool is_copy_constructible>
struct CopyConstructible {};

template <>
struct CopyConstructible<false> {
  constexpr CopyConstructible() = default;
307
  constexpr CopyConstructible(const CopyConstructible&) V8_NOEXCEPT = delete;
308 309 310
  constexpr CopyConstructible(CopyConstructible&&) V8_NOEXCEPT = default;
  CopyConstructible& operator=(const CopyConstructible&) V8_NOEXCEPT = default;
  CopyConstructible& operator=(CopyConstructible&&) V8_NOEXCEPT = default;
311 312 313 314 315 316 317 318
};

template <bool is_move_constructible>
struct MoveConstructible {};

template <>
struct MoveConstructible<false> {
  constexpr MoveConstructible() = default;
319
  constexpr MoveConstructible(const MoveConstructible&) V8_NOEXCEPT = default;
320
  constexpr MoveConstructible(MoveConstructible&&) V8_NOEXCEPT = delete;
321 322
  MoveConstructible& operator=(const MoveConstructible&) V8_NOEXCEPT = default;
  MoveConstructible& operator=(MoveConstructible&&) V8_NOEXCEPT = default;
323 324 325 326 327 328 329 330
};

template <bool is_copy_assignable>
struct CopyAssignable {};

template <>
struct CopyAssignable<false> {
  constexpr CopyAssignable() = default;
331 332
  constexpr CopyAssignable(const CopyAssignable&) V8_NOEXCEPT = default;
  constexpr CopyAssignable(CopyAssignable&&) V8_NOEXCEPT = default;
333
  CopyAssignable& operator=(const CopyAssignable&) V8_NOEXCEPT = delete;
334
  CopyAssignable& operator=(CopyAssignable&&) V8_NOEXCEPT = default;
335 336 337 338 339 340 341 342
};

template <bool is_move_assignable>
struct MoveAssignable {};

template <>
struct MoveAssignable<false> {
  constexpr MoveAssignable() = default;
343 344 345
  constexpr MoveAssignable(const MoveAssignable&) V8_NOEXCEPT = default;
  constexpr MoveAssignable(MoveAssignable&&) V8_NOEXCEPT = default;
  MoveAssignable& operator=(const MoveAssignable&) V8_NOEXCEPT = default;
346
  MoveAssignable& operator=(MoveAssignable&&) V8_NOEXCEPT = delete;
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
};

// Helper to conditionally enable converting constructors and assign operators.
template <typename T, typename U>
struct IsConvertibleFromOptional
    : std::integral_constant<
          bool, std::is_constructible<T, Optional<U>&>::value ||
                    std::is_constructible<T, const Optional<U>&>::value ||
                    std::is_constructible<T, Optional<U>&&>::value ||
                    std::is_constructible<T, const Optional<U>&&>::value ||
                    std::is_convertible<Optional<U>&, T>::value ||
                    std::is_convertible<const Optional<U>&, T>::value ||
                    std::is_convertible<Optional<U>&&, T>::value ||
                    std::is_convertible<const Optional<U>&&, T>::value> {};

template <typename T, typename U>
struct IsAssignableFromOptional
    : std::integral_constant<
          bool, IsConvertibleFromOptional<T, U>::value ||
                    std::is_assignable<T&, Optional<U>&>::value ||
                    std::is_assignable<T&, const Optional<U>&>::value ||
                    std::is_assignable<T&, Optional<U>&&>::value ||
                    std::is_assignable<T&, const Optional<U>&&>::value> {};

// Forward compatibility for C++17.
// Introduce one more deeper nested namespace to avoid leaking using std::swap.
namespace swappable_impl {
using std::swap;

struct IsSwappableImpl {
  // Tests if swap can be called. Check<T&>(0) returns true_type iff swap
  // is available for T. Otherwise, Check's overload resolution falls back
  // to Check(...) declared below thanks to SFINAE, so returns false_type.
  template <typename T>
  static auto Check(int i)
      -> decltype(swap(std::declval<T>(), std::declval<T>()), std::true_type());

  template <typename T>
  static std::false_type Check(...);
};
}  // namespace swappable_impl

template <typename T>
struct IsSwappable : decltype(swappable_impl::IsSwappableImpl::Check<T&>(0)) {};

// Forward compatibility for C++20.
template <typename T>
using RemoveCvRefT =
    typename std::remove_cv<typename std::remove_reference<T>::type>::type;

397 398
}  // namespace internal

399 400 401 402 403 404 405 406 407 408 409
// On Windows, by default, empty-base class optimization does not work,
// which means even if the base class is empty struct, it still consumes one
// byte for its body. __declspec(empty_bases) enables the optimization.
// cf)
// https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/
#ifdef OS_WIN
#define OPTIONAL_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
#else
#define OPTIONAL_DECLSPEC_EMPTY_BASES
#endif

410 411 412 413 414 415 416 417 418 419
// base::Optional is a Chromium version of the C++17 optional class:
// std::optional documentation:
// http://en.cppreference.com/w/cpp/utility/optional
// Chromium documentation:
// https://chromium.googlesource.com/chromium/src/+/master/docs/optional.md
//
// These are the differences between the specification and the implementation:
// - Constructors do not use 'constexpr' as it is a C++14 extension.
// - 'constexpr' might be missing in some places for reasons specified locally.
// - No exceptions are thrown, because they are banned from Chromium.
420
//   All copy/move constructors or assignment operators are marked V8_NOEXCEPT.
421
// - All the non-members are in the 'base' namespace instead of 'std'.
422 423 424 425 426 427 428
//
// Note that T cannot have a constructor T(Optional<T>) etc. Optional<T> checks
// T's constructor (specifically via IsConvertibleFromOptional), and in the
// check whether T can be constructible from Optional<T>, which is recursive
// so it does not work. As of Feb 2018, std::optional C++17 implementation in
// both clang and gcc has same limitation. MSVC SFINAE looks to have different
// behavior, but anyway it reports an error, too.
429
template <typename T>
430 431 432 433 434 435 436 437
class OPTIONAL_DECLSPEC_EMPTY_BASES Optional
    : public internal::OptionalBase<T>,
      public internal::CopyConstructible<std::is_copy_constructible<T>::value>,
      public internal::MoveConstructible<std::is_move_constructible<T>::value>,
      public internal::CopyAssignable<std::is_copy_constructible<T>::value &&
                                      std::is_copy_assignable<T>::value>,
      public internal::MoveAssignable<std::is_move_constructible<T>::value &&
                                      std::is_move_assignable<T>::value> {
438
 public:
439
#undef OPTIONAL_DECLSPEC_EMPTY_BASES
440 441
  using value_type = T;

442
  // Defer default/copy/move constructor implementation to OptionalBase.
443
  constexpr Optional() = default;
444 445
  constexpr Optional(const Optional& other) V8_NOEXCEPT = default;
  constexpr Optional(Optional&& other) V8_NOEXCEPT = default;
446 447 448 449 450 451 452 453 454 455 456 457 458

  constexpr Optional(nullopt_t) {}  // NOLINT(runtime/explicit)

  // Converting copy constructor. "explicit" only if
  // std::is_convertible<const U&, T>::value is false. It is implemented by
  // declaring two almost same constructors, but that condition in enable_if
  // is different, so that either one is chosen, thanks to SFINAE.
  template <typename U,
            typename std::enable_if<
                std::is_constructible<T, const U&>::value &&
                    !internal::IsConvertibleFromOptional<T, U>::value &&
                    std::is_convertible<const U&, T>::value,
                bool>::type = false>
459 460
  Optional(const Optional<U>& other) V8_NOEXCEPT
      : internal::OptionalBase<T>(other) {}
461 462 463 464 465 466 467

  template <typename U,
            typename std::enable_if<
                std::is_constructible<T, const U&>::value &&
                    !internal::IsConvertibleFromOptional<T, U>::value &&
                    !std::is_convertible<const U&, T>::value,
                bool>::type = false>
468
  explicit Optional(const Optional<U>& other) V8_NOEXCEPT
469 470 471 472 473 474 475 476 477 478
      : internal::OptionalBase<T>(other) {}

  // Converting move constructor. Similar to converting copy constructor,
  // declaring two (explicit and non-explicit) constructors.
  template <typename U,
            typename std::enable_if<
                std::is_constructible<T, U&&>::value &&
                    !internal::IsConvertibleFromOptional<T, U>::value &&
                    std::is_convertible<U&&, T>::value,
                bool>::type = false>
479 480
  Optional(Optional<U>&& other) V8_NOEXCEPT
      : internal::OptionalBase<T>(std::move(other)) {}
481 482 483 484 485 486 487

  template <typename U,
            typename std::enable_if<
                std::is_constructible<T, U&&>::value &&
                    !internal::IsConvertibleFromOptional<T, U>::value &&
                    !std::is_convertible<U&&, T>::value,
                bool>::type = false>
488
  explicit Optional(Optional<U>&& other) V8_NOEXCEPT
489
      : internal::OptionalBase<T>(std::move(other)) {}
490 491

  template <class... Args>
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
  constexpr explicit Optional(in_place_t, Args&&... args)
      : internal::OptionalBase<T>(in_place, std::forward<Args>(args)...) {}

  template <class U, class... Args,
            class = typename std::enable_if<std::is_constructible<
                value_type, std::initializer_list<U>&, Args...>::value>::type>
  constexpr explicit Optional(in_place_t, std::initializer_list<U> il,
                              Args&&... args)
      : internal::OptionalBase<T>(in_place, il, std::forward<Args>(args)...) {}

  // Forward value constructor. Similar to converting constructors,
  // conditionally explicit.
  template <
      typename U = value_type,
      typename std::enable_if<
          std::is_constructible<T, U&&>::value &&
              !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
              !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
              std::is_convertible<U&&, T>::value,
          bool>::type = false>
  constexpr Optional(U&& value)  // NOLINT(runtime/explicit)
      : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}

  template <
      typename U = value_type,
      typename std::enable_if<
          std::is_constructible<T, U&&>::value &&
              !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
              !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
              !std::is_convertible<U&&, T>::value,
          bool>::type = false>
  constexpr explicit Optional(U&& value)
      : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
525 526 527

  ~Optional() = default;

528
  // Defer copy-/move- assign operator implementation to OptionalBase.
529 530
  Optional& operator=(const Optional& other) V8_NOEXCEPT = default;
  Optional& operator=(Optional&& other) V8_NOEXCEPT = default;
531 532

  Optional& operator=(nullopt_t) {
533 534 535 536
    FreeIfNeeded();
    return *this;
  }

537 538 539 540 541 542 543 544 545
  // Perfect-forwarded assignment.
  template <typename U>
  typename std::enable_if<
      !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
          std::is_constructible<T, U>::value &&
          std::is_assignable<T&, U>::value &&
          (!std::is_scalar<T>::value ||
           !std::is_same<typename std::decay<U>::type, T>::value),
      Optional&>::type
546
  operator=(U&& value) V8_NOEXCEPT {
547
    InitOrAssign(std::forward<U>(value));
548 549 550
    return *this;
  }

551 552 553 554 555 556
  // Copy assign the state of other.
  template <typename U>
  typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
                              std::is_constructible<T, const U&>::value &&
                              std::is_assignable<T&, const U&>::value,
                          Optional&>::type
557
  operator=(const Optional<U>& other) V8_NOEXCEPT {
558
    CopyAssign(other);
559 560 561
    return *this;
  }

562 563 564 565 566
  // Move assign the state of other.
  template <typename U>
  typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
                              std::is_constructible<T, U>::value &&
                              std::is_assignable<T&, U>::value,
567
                          Optional&>::type
568
  operator=(Optional<U>&& other) V8_NOEXCEPT {
569
    MoveAssign(std::move(other));
570 571 572 573
    return *this;
  }

  const T* operator->() const {
574 575
    DCHECK(storage_.is_populated_);
    return &storage_.value_;
576 577 578
  }

  T* operator->() {
579 580
    DCHECK(storage_.is_populated_);
    return &storage_.value_;
581 582
  }

583 584 585 586
  const T& operator*() const & {
    DCHECK(storage_.is_populated_);
    return storage_.value_;
  }
587

588 589 590 591
  T& operator*() & {
    DCHECK(storage_.is_populated_);
    return storage_.value_;
  }
592

593 594 595 596
  const T&& operator*() const && {
    DCHECK(storage_.is_populated_);
    return std::move(storage_.value_);
  }
597

598 599 600 601
  T&& operator*() && {
    DCHECK(storage_.is_populated_);
    return std::move(storage_.value_);
  }
602

603
  constexpr explicit operator bool() const { return storage_.is_populated_; }
604

605
  constexpr bool has_value() const { return storage_.is_populated_; }
606 607

  T& value() & {
608
    CHECK(storage_.is_populated_);
609 610 611 612
    return storage_.value_;
  }

  const T& value() const & {
613
    CHECK(storage_.is_populated_);
614 615 616 617
    return storage_.value_;
  }

  T&& value() && {
618
    CHECK(storage_.is_populated_);
619 620 621 622
    return std::move(storage_.value_);
  }

  const T&& value() const && {
623
    CHECK(storage_.is_populated_);
624 625 626 627 628 629 630 631 632 633
    return std::move(storage_.value_);
  }

  template <class U>
  constexpr T value_or(U&& default_value) const & {
    // TODO(mlamouri): add the following assert when possible:
    // static_assert(std::is_copy_constructible<T>::value,
    //               "T must be copy constructible");
    static_assert(std::is_convertible<U, T>::value,
                  "U must be convertible to T");
634 635 636
    return storage_.is_populated_
               ? storage_.value_
               : static_cast<T>(std::forward<U>(default_value));
637 638 639 640 641 642 643 644 645
  }

  template <class U>
  T value_or(U&& default_value) && {
    // TODO(mlamouri): add the following assert when possible:
    // static_assert(std::is_move_constructible<T>::value,
    //               "T must be move constructible");
    static_assert(std::is_convertible<U, T>::value,
                  "U must be convertible to T");
646 647 648
    return storage_.is_populated_
               ? std::move(storage_.value_)
               : static_cast<T>(std::forward<U>(default_value));
649 650 651
  }

  void swap(Optional& other) {
652
    if (!storage_.is_populated_ && !other.storage_.is_populated_) return;
653

654 655 656
    if (storage_.is_populated_ != other.storage_.is_populated_) {
      if (storage_.is_populated_) {
        other.storage_.Init(std::move(storage_.value_));
657
        FreeIfNeeded();
658 659 660
      } else {
        storage_.Init(std::move(other.storage_.value_));
        other.FreeIfNeeded();
661 662 663 664
      }
      return;
    }

665
    DCHECK(storage_.is_populated_ && other.storage_.is_populated_);
666 667 668 669 670 671 672
    using std::swap;
    swap(**this, *other);
  }

  void reset() { FreeIfNeeded(); }

  template <class... Args>
673
  T& emplace(Args&&... args) {
674
    FreeIfNeeded();
675 676
    storage_.Init(std::forward<Args>(args)...);
    return storage_.value_;
677 678
  }

679 680 681 682 683 684 685 686
  template <class U, class... Args>
  typename std::enable_if<
      std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
      T&>::type
  emplace(std::initializer_list<U> il, Args&&... args) {
    FreeIfNeeded();
    storage_.Init(il, std::forward<Args>(args)...);
    return storage_.value_;
687 688
  }

689 690 691 692 693 694 695 696
 private:
  // Accessing template base class's protected member needs explicit
  // declaration to do so.
  using internal::OptionalBase<T>::CopyAssign;
  using internal::OptionalBase<T>::FreeIfNeeded;
  using internal::OptionalBase<T>::InitOrAssign;
  using internal::OptionalBase<T>::MoveAssign;
  using internal::OptionalBase<T>::storage_;
697 698
};

699 700 701 702 703 704 705 706 707
// Here after defines comparation operators. The definition follows
// http://en.cppreference.com/w/cpp/utility/optional/operator_cmp
// while bool() casting is replaced by has_value() to meet the chromium
// style guide.
template <class T, class U>
bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) {
  if (lhs.has_value() != rhs.has_value()) return false;
  if (!lhs.has_value()) return true;
  return *lhs == *rhs;
708 709
}

710 711 712 713 714
template <class T, class U>
bool operator!=(const Optional<T>& lhs, const Optional<U>& rhs) {
  if (lhs.has_value() != rhs.has_value()) return true;
  if (!lhs.has_value()) return false;
  return *lhs != *rhs;
715 716
}

717 718 719 720 721
template <class T, class U>
bool operator<(const Optional<T>& lhs, const Optional<U>& rhs) {
  if (!rhs.has_value()) return false;
  if (!lhs.has_value()) return true;
  return *lhs < *rhs;
722 723
}

724 725 726 727 728
template <class T, class U>
bool operator<=(const Optional<T>& lhs, const Optional<U>& rhs) {
  if (!lhs.has_value()) return true;
  if (!rhs.has_value()) return false;
  return *lhs <= *rhs;
729 730
}

731 732 733 734 735
template <class T, class U>
bool operator>(const Optional<T>& lhs, const Optional<U>& rhs) {
  if (!lhs.has_value()) return false;
  if (!rhs.has_value()) return true;
  return *lhs > *rhs;
736 737
}

738 739 740 741 742
template <class T, class U>
bool operator>=(const Optional<T>& lhs, const Optional<U>& rhs) {
  if (!rhs.has_value()) return true;
  if (!lhs.has_value()) return false;
  return *lhs >= *rhs;
743 744 745
}

template <class T>
746
constexpr bool operator==(const Optional<T>& opt, nullopt_t) {
747 748 749 750
  return !opt;
}

template <class T>
751
constexpr bool operator==(nullopt_t, const Optional<T>& opt) {
752 753 754 755
  return !opt;
}

template <class T>
756 757
constexpr bool operator!=(const Optional<T>& opt, nullopt_t) {
  return opt.has_value();
758 759 760
}

template <class T>
761 762
constexpr bool operator!=(nullopt_t, const Optional<T>& opt) {
  return opt.has_value();
763 764 765
}

template <class T>
766
constexpr bool operator<(const Optional<T>& opt, nullopt_t) {
767 768 769 770
  return false;
}

template <class T>
771 772
constexpr bool operator<(nullopt_t, const Optional<T>& opt) {
  return opt.has_value();
773 774 775
}

template <class T>
776
constexpr bool operator<=(const Optional<T>& opt, nullopt_t) {
777 778 779 780
  return !opt;
}

template <class T>
781
constexpr bool operator<=(nullopt_t, const Optional<T>& opt) {
782 783 784 785
  return true;
}

template <class T>
786 787
constexpr bool operator>(const Optional<T>& opt, nullopt_t) {
  return opt.has_value();
788 789 790
}

template <class T>
791
constexpr bool operator>(nullopt_t, const Optional<T>& opt) {
792 793 794 795
  return false;
}

template <class T>
796
constexpr bool operator>=(const Optional<T>& opt, nullopt_t) {
797 798 799 800
  return true;
}

template <class T>
801
constexpr bool operator>=(nullopt_t, const Optional<T>& opt) {
802 803 804
  return !opt;
}

805 806 807
template <class T, class U>
constexpr bool operator==(const Optional<T>& opt, const U& value) {
  return opt.has_value() ? *opt == value : false;
808 809
}

810 811 812
template <class T, class U>
constexpr bool operator==(const U& value, const Optional<T>& opt) {
  return opt.has_value() ? value == *opt : false;
813 814
}

815 816 817
template <class T, class U>
constexpr bool operator!=(const Optional<T>& opt, const U& value) {
  return opt.has_value() ? *opt != value : true;
818 819
}

820 821 822
template <class T, class U>
constexpr bool operator!=(const U& value, const Optional<T>& opt) {
  return opt.has_value() ? value != *opt : true;
823 824
}

825 826 827
template <class T, class U>
constexpr bool operator<(const Optional<T>& opt, const U& value) {
  return opt.has_value() ? *opt < value : true;
828 829
}

830 831 832
template <class T, class U>
constexpr bool operator<(const U& value, const Optional<T>& opt) {
  return opt.has_value() ? value < *opt : false;
833 834
}

835 836 837
template <class T, class U>
constexpr bool operator<=(const Optional<T>& opt, const U& value) {
  return opt.has_value() ? *opt <= value : true;
838 839
}

840 841 842
template <class T, class U>
constexpr bool operator<=(const U& value, const Optional<T>& opt) {
  return opt.has_value() ? value <= *opt : false;
843 844
}

845 846 847
template <class T, class U>
constexpr bool operator>(const Optional<T>& opt, const U& value) {
  return opt.has_value() ? *opt > value : false;
848 849
}

850 851 852
template <class T, class U>
constexpr bool operator>(const U& value, const Optional<T>& opt) {
  return opt.has_value() ? value > *opt : true;
853 854
}

855 856 857
template <class T, class U>
constexpr bool operator>=(const Optional<T>& opt, const U& value) {
  return opt.has_value() ? *opt >= value : false;
858 859
}

860 861 862
template <class T, class U>
constexpr bool operator>=(const U& value, const Optional<T>& opt) {
  return opt.has_value() ? value >= *opt : true;
863 864 865 866 867 868 869
}

template <class T>
constexpr Optional<typename std::decay<T>::type> make_optional(T&& value) {
  return Optional<typename std::decay<T>::type>(std::forward<T>(value));
}

870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
template <class T, class... Args>
constexpr Optional<T> make_optional(Args&&... args) {
  return Optional<T>(in_place, std::forward<Args>(args)...);
}

template <class T, class U, class... Args>
constexpr Optional<T> make_optional(std::initializer_list<U> il,
                                    Args&&... args) {
  return Optional<T>(in_place, il, std::forward<Args>(args)...);
}

// Partial specialization for a function template is not allowed. Also, it is
// not allowed to add overload function to std namespace, while it is allowed
// to specialize the template in std. Thus, swap() (kind of) overloading is
// defined in base namespace, instead.
885
template <class T>
886 887 888
typename std::enable_if<std::is_move_constructible<T>::value &&
                        internal::IsSwappable<T>::value>::type
swap(Optional<T>& lhs, Optional<T>& rhs) {
889 890 891 892 893 894 895
  lhs.swap(rhs);
}

}  // namespace base
}  // namespace v8

#endif  // V8_BASE_OPTIONAL_H_