xref: /freebsd-src/contrib/llvm-project/libcxx/include/__utility/no_destroy.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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