#pragma once #include #include #include "WAVM/Inline/BasicTypes.h" namespace WAVM { // A type that holds an optional instance of another type. The lifetime of the contained // instance is defined by the user of this type, and the user is responsible for calling // construct and destruct. template::value> struct OptionalStorage { template void construct(Args&&... args) { new(&contents) Contents(std::forward(args)...); } void destruct() { get().~Contents(); } #if __cplusplus >= 201703L Contents& get() { return *std::launder(reinterpret_cast(&contents)); } const Contents& get() const { return *std::launder(reinterpret_cast(&contents)); } #else Contents& get() { return *reinterpret_cast(&contents); } const Contents& get() const { return *reinterpret_cast(&contents); } #endif private: typename std::aligned_storage::type contents; }; // Partial specialization for types with trivial destructors. template struct OptionalStorage { template void construct(Args&&... args) { new(&contents) Contents(std::forward(args)...); } void destruct() {} #if __cplusplus >= 201703L Contents& get() { return *std::launder(reinterpret_cast(&contents)); } const Contents& get() const { return *std::launder(reinterpret_cast(&contents)); } #else Contents& get() { return *reinterpret_cast(&contents); } const Contents& get() const { return *reinterpret_cast(&contents); } #endif private: typename std::aligned_storage::type contents; }; namespace OptionalStorageAssertions { struct NonTrivialType { NonTrivialType(); }; static_assert(std::is_trivial>::value, "OptionalStorage is non-trivial"); }; }