%PDF- %PDF-
| Direktori : /home2/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/base/ |
| Current File : //home2/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/base/discriminated-union.h |
// Copyright 2023 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.
#ifndef V8_BASE_DISCRIMINATED_UNION_H_
#define V8_BASE_DISCRIMINATED_UNION_H_
#include <type_traits>
#include <utility>
#include "src/base/compiler-specific.h"
#include "src/base/template-utils.h"
namespace v8 {
namespace base {
// A variant-like discriminated union type, which takes a discriminating enum
// and a set of types. The enum must have as many elements as the number of
// types, with each enum value corresponding to one type in the set.
//
// Example usage:
//
// enum class FooType {
// kBar,
// kBaz
// }
// class Bar { ... };
// class Baz { ... };
//
// // FooType::kBar and FooType::kBaz match Bar and Baz, respectively.
// DiscriminatedUnion<FooType, Bar, Baz> union;
//
// switch (union.tag()) {
// case FooType::kBar:
// return process_bar(union.get<FooType::kBar>);
// case FooType::kBaz:
// return process_baz(union.get<FooType::kBaz>);
// }
template <typename TagEnum, typename... Ts>
class DiscriminatedUnion {
public:
// All Ts must be trivially destructible to avoid DiscriminatedUnion needing a
// destructor.
static_assert((std::is_trivially_destructible_v<Ts> && ...));
using Tag = TagEnum;
DiscriminatedUnion(DiscriminatedUnion&& other) V8_NOEXCEPT = default;
DiscriminatedUnion(const DiscriminatedUnion& other) V8_NOEXCEPT = default;
DiscriminatedUnion& operator=(DiscriminatedUnion&& other)
V8_NOEXCEPT = default;
DiscriminatedUnion& operator=(const DiscriminatedUnion& other)
V8_NOEXCEPT = default;
// TODO(leszeks): Add in-place constructor.
// Construct with known tag and type (the tag is DCHECKed).
template <typename T>
constexpr explicit DiscriminatedUnion(Tag tag, T&& data) V8_NOEXCEPT {
constexpr size_t index = index_of_type_v<std::decay_t<T>, Ts...>;
static_assert(index < sizeof...(Ts));
static_assert(index < std::numeric_limits<uint8_t>::max());
// TODO(leszeks): Support unions with repeated types.
DCHECK_EQ(tag, static_cast<Tag>(index));
tag_ = static_cast<uint8_t>(index);
new (&data_) T(std::forward<T>(data));
}
// Construct with known type.
template <typename T>
constexpr explicit DiscriminatedUnion(T&& data) V8_NOEXCEPT {
constexpr size_t index = index_of_type_v<std::decay_t<T>, Ts...>;
static_assert(index < sizeof...(Ts));
static_assert(index < std::numeric_limits<uint8_t>::max());
tag_ = static_cast<uint8_t>(index);
new (&data_) T(std::forward<T>(data));
}
constexpr Tag tag() const { return static_cast<Tag>(tag_); }
// Get union member by tag.
template <Tag tag>
constexpr const auto& get() const {
using T = nth_type_t<static_cast<size_t>(tag), Ts...>;
DCHECK_EQ(tag, this->tag());
return reinterpret_cast<const T&>(data_);
}
// Get union member by tag.
template <Tag tag>
constexpr auto& get() {
using T = nth_type_t<static_cast<size_t>(tag), Ts...>;
DCHECK_EQ(tag, this->tag());
return reinterpret_cast<T&>(data_);
}
// Get union member by type.
template <typename T>
constexpr const auto& get() const {
DCHECK_EQ(static_cast<Tag>(index_of_type_v<T, Ts...>), this->tag());
return reinterpret_cast<const T&>(data_);
}
// Get union member by type.
template <typename T>
constexpr auto& get() {
DCHECK_EQ(static_cast<Tag>(index_of_type_v<T, Ts...>), this->tag());
return reinterpret_cast<T&>(data_);
}
private:
alignas(std::max({alignof(Ts)...})) char data_[std::max({sizeof(Ts)...})];
static_assert(sizeof...(Ts) <= std::numeric_limits<uint8_t>::max());
uint8_t tag_;
};
} // namespace base
} // namespace v8
#endif // V8_BASE_DISCRIMINATED_UNION_H_