15f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric 95f757f3fSDimitry Andric #ifndef _LIBCPP___UTILITY_NO_DESTROY_H 105f757f3fSDimitry Andric #define _LIBCPP___UTILITY_NO_DESTROY_H 115f757f3fSDimitry Andric 125f757f3fSDimitry Andric #include <__config> 135f757f3fSDimitry Andric #include <__type_traits/is_constant_evaluated.h> 145f757f3fSDimitry Andric #include <__utility/forward.h> 15*0fca6ea1SDimitry Andric #include <new> 165f757f3fSDimitry Andric 175f757f3fSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 185f757f3fSDimitry Andric # pragma GCC system_header 195f757f3fSDimitry Andric #endif 205f757f3fSDimitry Andric 215f757f3fSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 225f757f3fSDimitry Andric 235f757f3fSDimitry Andric struct __uninitialized_tag {}; 245f757f3fSDimitry Andric 255f757f3fSDimitry Andric // This class stores an object of type _Tp but never destroys it. 265f757f3fSDimitry Andric // 275f757f3fSDimitry Andric // This is akin to using __attribute__((no_destroy)), except that it is possible 285f757f3fSDimitry Andric // to control the lifetime of the object with more flexibility by deciding e.g. 295f757f3fSDimitry Andric // whether to initialize the object at construction or to defer to a later 305f757f3fSDimitry Andric // initialization using __emplace. 315f757f3fSDimitry Andric template <class _Tp> 325f757f3fSDimitry Andric struct __no_destroy { 33*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __no_destroy(__uninitialized_tag) : __obj_() {} 34*0fca6ea1SDimitry Andric 35*0fca6ea1SDimitry Andric template <class... _Args> 36*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __no_destroy(_Args&&... __args) { 37*0fca6ea1SDimitry Andric ::new ((void*)__obj_) _Tp(std::forward<_Args>(__args)...); 385f757f3fSDimitry Andric } 395f757f3fSDimitry Andric 405f757f3fSDimitry Andric template <class... _Args> 41*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp& __emplace(_Args&&... __args) { 42*0fca6ea1SDimitry Andric return *(::new ((void*)__obj_) _Tp(std::forward<_Args>(__args)...)); 435f757f3fSDimitry Andric } 445f757f3fSDimitry Andric 45*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp& __get() { return *reinterpret_cast<_Tp*>(__obj_); } 46*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp const& __get() const { return *reinterpret_cast<const _Tp*>(__obj_); } 475f757f3fSDimitry Andric 485f757f3fSDimitry Andric private: 49*0fca6ea1SDimitry Andric _ALIGNAS_TYPE(_Tp) char __obj_[sizeof(_Tp)]; 505f757f3fSDimitry Andric }; 515f757f3fSDimitry Andric 525f757f3fSDimitry Andric _LIBCPP_END_NAMESPACE_STD 535f757f3fSDimitry Andric 545f757f3fSDimitry Andric #endif // _LIBCPP___UTILITY_NO_DESTROY_H 55