/** This file is a part of rexy's general purpose library Copyright (C) 2022 rexy712 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef REXY_STORAGE_FOR_TPP #define REXY_STORAGE_FOR_TPP #include //forward, move #if __cplusplus >= 202002L && __has_cpp_attribute(no_unique_address) && __cpp_constexpr >= 202002L #include //construct_at, destroy_at namespace rexy{ template template constexpr storage_for::storage_for(Args&&... args)noexcept(std::is_nothrow_constructible::value){ std::construct_at(&m_storage.data, std::forward(args)...); m_dirty = 1; } template constexpr storage_for::storage_for(const_reference t)noexcept(std::is_nothrow_copy_constructible::value){ std::construct_at(&m_storage.data, t); m_dirty = 1; } template constexpr storage_for::storage_for(rvalue_reference t)noexcept(std::is_nothrow_move_constructible::value){ std::construct_at(&m_storage.data, std::move(t)); m_dirty = 1; } template constexpr storage_for::storage_for(const storage_for& s)noexcept(std::is_nothrow_copy_constructible::value){ if(s.m_dirty){ std::construct_at(&m_storage.data, s.m_storage.data); m_dirty = 1; } } template constexpr storage_for::storage_for(storage_for&& s)noexcept(std::is_nothrow_move_constructible::value){ if(s.m_dirty){ std::construct_at(&m_storage.data, std::move(s.m_storage.data)); m_dirty = 1; } } template REXY_CPP20_CONSTEXPR storage_for::~storage_for(void)noexcept(std::is_nothrow_destructible::value){ if(m_dirty){ destroy(); } } template constexpr storage_for& storage_for::operator=(const storage_for& s)noexcept(std::is_nothrow_copy_assignable::value){ return ((*this) = storage_for(s)); } template constexpr storage_for& storage_for::operator=(storage_for&& s)noexcept(std::is_nothrow_move_assignable::value){ if(s.m_dirty){ return ((*this) = std::move(s.m_storage.data)); }else{ if(m_dirty){ destroy(); } } return *this; } template constexpr storage_for& storage_for::operator=(const_reference t)noexcept(std::is_nothrow_copy_assignable::value){ if(m_dirty){ m_storage.data = t; }else{ std::construct_at(&m_storage.data, t); } m_dirty = 1; return *this; } template constexpr storage_for& storage_for::operator=(rvalue_reference t)noexcept(std::is_nothrow_move_assignable::value){ if(m_dirty){ m_storage.data = std::move(t); }else{ std::construct_at(&m_storage.data, std::move(t)); } m_dirty = 1; return *this; } template constexpr void storage_for::destroy(void)noexcept(std::is_nothrow_destructible::value){ if(m_dirty){ std::destroy_at(&m_storage.data); m_dirty = 0; } } template constexpr storage_for::operator reference(void)noexcept{ return m_storage.data; } template constexpr storage_for::operator const_reference(void)const noexcept{ return m_storage.data; } template constexpr storage_for::operator rvalue_reference(void)&& noexcept{ return std::move(m_storage.data); } template constexpr auto storage_for::get(void)noexcept -> reference{ return m_storage.data; } template constexpr auto storage_for::get(void)const noexcept -> const_reference{ return m_storage.data; } template constexpr auto storage_for::operator->(void)noexcept -> pointer{ return &m_storage.data; } template constexpr auto storage_for::operator->(void)const noexcept -> const_pointer{ return &m_storage.data; } template constexpr auto storage_for::operator*(void)noexcept -> reference{ return m_storage.data; } template constexpr auto storage_for::operator*(void)const noexcept -> const_reference{ return m_storage.data; } template constexpr bool storage_for::valid(void)const{ return m_dirty; } } #else //__cplusplus namespace rexy{ template template constexpr storage_for::storage_for(Args&&... args)noexcept(std::is_nothrow_constructible::value){ new (m_storage) T(std::forward(args)...); m_dirty = 1; } template constexpr storage_for::storage_for(const_reference t)noexcept(std::is_nothrow_copy_constructible::value){ new (m_storage) T(t); m_dirty = 1; } template constexpr storage_for::storage_for(rvalue_reference t)noexcept(std::is_nothrow_move_constructible::value){ new (m_storage) T(std::move(t)); m_dirty = 1; } template constexpr storage_for::storage_for(const storage_for& s)noexcept(std::is_nothrow_copy_constructible::value){ new (m_storage) T(reinterpret_cast(s.m_storage)); m_dirty = 1; } template constexpr storage_for::storage_for(storage_for&& s)noexcept(std::is_nothrow_move_constructible::value){ new (m_storage) T(std::move(reinterpret_cast(&s.m_storage))); m_dirty = 1; } template REXY_CPP20_CONSTEXPR storage_for::~storage_for(void)noexcept(std::is_nothrow_destructible::value){ if(m_dirty){ destroy(); } } template constexpr storage_for& storage_for::operator=(const storage_for& s)noexcept(std::is_nothrow_copy_assignable::value){ reinterpret_cast(m_storage) = static_cast(s); return *this; } template constexpr storage_for& storage_for::operator=(storage_for&& s)noexcept(std::is_nothrow_move_assignable::value){ reinterpret_cast(m_storage) = static_cast(std::move(s)); return *this; } template constexpr storage_for& storage_for::operator=(const_reference t)noexcept(std::is_nothrow_copy_assignable::value){ reinterpret_cast(m_storage) = t; return *this; } template constexpr storage_for& storage_for::operator=(rvalue_reference t)noexcept(std::is_nothrow_move_assignable::value){ reinterpret_cast(m_storage) = std::move(t); return *this; } template constexpr void storage_for::destroy(void)noexcept(std::is_nothrow_destructible::value){ reinterpret_cast(&m_storage)->~T(); m_dirty = 0; } template constexpr storage_for::operator reference(void)noexcept{ return reinterpret_cast(m_storage); } template constexpr storage_for::operator const_reference(void)const noexcept{ return reinterpret_cast(m_storage); } template constexpr storage_for::operator rvalue_reference(void)&& noexcept{ return reinterpret_cast(std::move(m_storage)); } template constexpr auto storage_for::get(void)noexcept -> reference{ return reinterpret_cast(m_storage); } template constexpr auto storage_for::get(void)const noexcept -> const_reference{ return reinterpret_cast(m_storage); } template constexpr auto storage_for::operator->(void)noexcept -> pointer{ return reinterpret_cast(&m_storage); } template constexpr auto storage_for::operator->(void)const noexcept -> const_pointer{ return reinterpret_cast(&m_storage); } template constexpr auto storage_for::operator*(void)noexcept -> reference{ return reinterpret_cast(m_storage); } template constexpr auto storage_for::operator*(void)const noexcept -> const_reference{ return reinterpret_cast(m_storage); } template constexpr bool storage_for::valid(void)const{ return m_dirty; } } #endif //__cplusplus #endif