%PDF- %PDF-
Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/base/ |
Current File : /home/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_