diff options
Diffstat (limited to 'nihil.generator/manual_lifetime.ccm')
| -rw-r--r-- | nihil.generator/manual_lifetime.ccm | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/nihil.generator/manual_lifetime.ccm b/nihil.generator/manual_lifetime.ccm new file mode 100644 index 0000000..d249e99 --- /dev/null +++ b/nihil.generator/manual_lifetime.ccm @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////////////////////// +// Reference implementation of std::generator proposal P2168. +// +// See https://wg21.link/P2168 for details. +// +/////////////////////////////////////////////////////////////////////////////// +// Copyright Lewis Baker, Corentin Jabot +// +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. +// (See accompanying file LICENSE or http://www.boost.org/LICENSE_1_0.txt) +/////////////////////////////////////////////////////////////////////////////// + +module; + +#include <concepts> +#include <memory> + +export module nihil.generator:manual_lifetime; + +namespace nihil { + +template <typename T> +struct manual_lifetime { + manual_lifetime() noexcept {} + ~manual_lifetime() {} + + template <typename ...Args> + auto construct(this manual_lifetime &self, Args && ...args) + noexcept(std::is_nothrow_constructible_v<T, Args...>) + -> T & + { + return *::new (static_cast<void*>(std::addressof(self.m_value))) + T(static_cast<Args &&>(args)...); + } + + void destruct(this manual_lifetime &self) + noexcept(std::is_nothrow_destructible_v<T>) + { + self.m_value.~T(); + } + + auto get(this manual_lifetime &self) noexcept -> T & + { + return self.m_value; + } + + auto get(this manual_lifetime &&self) noexcept -> T && + { + return static_cast<T&&>(self.m_value); + } + + auto get(this manual_lifetime const &self) noexcept -> T const & + { + return self.m_value; + } + + auto get(this manual_lifetime const &&self) noexcept -> T const && + { + return static_cast<T const &&>(self.m_value); + } + +private: + union { + std::remove_const_t<T> m_value; + }; +}; + +template <typename T> +class manual_lifetime<T &> { + manual_lifetime() noexcept {} + ~manual_lifetime() {} + + auto construct(this manual_lifetime &self, T &value) noexcept -> T & + { + self.m_value = std::addressof(value); + return self.m_value; + } + + auto destruct(this manual_lifetime &) noexcept -> void + { + } + + auto get(this manual_lifetime const &self) noexcept -> T & + { + return *self.m_value; + } + +private: + T *m_value = nullptr; +}; + +template <typename T> +class manual_lifetime<T &&> { + manual_lifetime() noexcept {} + ~manual_lifetime() {} + + auto construct(this manual_lifetime &self, T &&value) noexcept -> T && + { + self.m_value = std::addressof(value); + return static_cast<T &&>(value); + } + + void destruct(this manual_lifetime &) noexcept + { + } + + auto get(this manual_lifetime const &self) noexcept -> T && + { + return static_cast<T &&>(*self.m_value); + } + +private: + T* m_value = nullptr; +}; + +} |
