/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License Version 2.0 with LLVM Exceptions * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * https://llvm.org/LICENSE.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include namespace unifex { template class manual_lifetime_union { public: manual_lifetime_union() = default; template [[maybe_unused]] T& construct(Args&&... args) noexcept( std::is_nothrow_constructible_v) { return unifex::activate_union_member( *static_cast*>(static_cast(&storage_)), static_cast(args)...); } template [[maybe_unused]] T& construct_with(Func&& func) noexcept(is_nothrow_callable_v) { return unifex::activate_union_member_with( *static_cast*>(static_cast(&storage_)), static_cast(func)); } template void destruct() noexcept { unifex::deactivate_union_member( *static_cast*>(static_cast(&storage_))); } template decltype(auto) get() & noexcept { static_assert(is_one_of_v); return static_cast*>(static_cast(&storage_)) ->get(); } template decltype(auto) get() const & noexcept { static_assert(is_one_of_v); return static_cast const*>( static_cast(&storage_))->get(); } template decltype(auto) get() && noexcept { static_assert(is_one_of_v); return std::move( *static_cast*>(static_cast(&storage_))).get(); } private: std::aligned_union_t<0, manual_lifetime...> storage_; }; template <> class manual_lifetime_union<> {}; // For activating a manual_lifetime_union when it is in a union and initializing // its value from arguments to its constructor. template [[maybe_unused]] // T& activate_union_member(manual_lifetime_union& box, Args&&... args) // noexcept(std::is_nothrow_constructible_v) { auto* p = ::new (&box) manual_lifetime_union{}; scope_guard guard = [=]() noexcept { p->~manual_lifetime_union(); }; auto& t = p->template construct(static_cast(args)...); guard.release(); return t; } // For activating a manual_lifetime_union when it is in a union and initializing // its value from the result of calling a function. template [[maybe_unused]] // T& activate_union_member_with(manual_lifetime_union& box, Func&& func) noexcept(is_nothrow_callable_v) { auto* p = ::new (&box) manual_lifetime_union{}; scope_guard guard = [=]() noexcept { p->~manual_lifetime_union(); }; auto& t = p->template construct_with(static_cast(func)); guard.release(); return t; } // For deactivating a manual_lifetime_union when it is in a union template void deactivate_union_member(manual_lifetime_union& box) noexcept { box.template destruct(); box.~manual_lifetime_union(); } } // namespace unifex #include