diff --git a/CMakeLists.txt b/CMakeLists.txt
index 227216f..49cbdb2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,7 +39,7 @@ if(BUILD_TESTS)
add_subdirectory(tests)
endif()
-set(LIBREXY_PUBLIC_HEADERS "include/rexy/rexy.hpp" "include/rexy/algorithm.hpp" "include/rexy/utility.hpp" "include/rexy/basic_string_hash.hpp" "include/rexy/hash.hpp" "include/rexy/static_string_hash.hpp" "include/rexy/string_hash.hpp" "include/rexy/mpmc_queue.hpp" "include/rexy/mpmc_queue.tpp" "include/rexy/traits.hpp" "include/rexy/steal.hpp" "include/rexy/binary.hpp" "include/rexy/expression.hpp" "include/rexy/binary_base.hpp" "include/rexy/binary_base.tpp" "include/rexy/string_base.hpp" "include/rexy/string.hpp" "include/rexy/filerd.hpp" "include/rexy/string_base.tpp" "include/rexy/allocator.hpp" "include/rexy/meta.hpp" "include/rexy/buffer.hpp" "include/rexy/buffer.tpp" "include/rexy/debug_print.hpp" "include/rexy/deferred.hpp" "include/rexy/demangle.hpp" "include/rexy/enum_traits.hpp" "include/rexy/source_location.hpp")
+set(LIBREXY_PUBLIC_HEADERS "include/rexy/rexy.hpp" "include/rexy/algorithm.hpp" "include/rexy/utility.hpp" "include/rexy/basic_string_hash.hpp" "include/rexy/hash.hpp" "include/rexy/static_string_hash.hpp" "include/rexy/string_hash.hpp" "include/rexy/mpmc_queue.hpp" "include/rexy/mpmc_queue.tpp" "include/rexy/traits.hpp" "include/rexy/steal.hpp" "include/rexy/binary.hpp" "include/rexy/expression.hpp" "include/rexy/binary_base.hpp" "include/rexy/binary_base.tpp" "include/rexy/string_base.hpp" "include/rexy/string.hpp" "include/rexy/filerd.hpp" "include/rexy/string_base.tpp" "include/rexy/allocator.hpp" "include/rexy/meta.hpp" "include/rexy/buffer.hpp" "include/rexy/buffer.tpp" "include/rexy/debug_print.hpp" "include/rexy/deferred.hpp" "include/rexy/demangle.hpp" "include/rexy/enum_traits.hpp" "include/rexy/source_location.hpp" "include/rexy/storage_for.hpp" "include/rexy/storage_for.tpp")
target_compile_options(rexy PRIVATE -Wall -Wextra -pedantic -std=c++20)
install(TARGETS rexy
diff --git a/include/rexy/storage_for.hpp b/include/rexy/storage_for.hpp
new file mode 100644
index 0000000..3d308e4
--- /dev/null
+++ b/include/rexy/storage_for.hpp
@@ -0,0 +1,80 @@
+/**
+ 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_HPP
+#define REXY_STORAGE_FOR_HPP
+
+#include //forward, move
+#include //is_nothrow_constructible, etc
+
+namespace rexy{
+
+ //A wrapper around raw storage.
+ //Allows default constructing objects with members which cannot be default constructed
+
+ template
+ class storage_for
+ {
+ public:
+ using value_type = T;
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using rvalue_reference = T&&;
+
+ static constexpr auto align = alignof(value_type);
+ static constexpr auto size = sizeof(value_type);
+
+ private:
+ alignas(align) unsigned char m_storage[size];
+ unsigned char m_dirty:1 = 0;
+
+ public:
+ constexpr storage_for(void) = default;
+ template
+ constexpr storage_for(Args&&... args)noexcept(std::is_nothrow_constructible::value);
+ constexpr storage_for(const_reference t)noexcept(std::is_nothrow_copy_constructible::value);
+ constexpr storage_for(rvalue_reference t)noexcept(std::is_nothrow_move_constructible::value);
+ constexpr storage_for(const storage_for& s)noexcept(std::is_nothrow_copy_constructible::value);
+ constexpr storage_for(storage_for&& s)noexcept(std::is_nothrow_move_constructible::value);
+ constexpr ~storage_for(void)noexcept(std::is_nothrow_destructible::value);
+
+ constexpr storage_for& operator=(const storage_for& s)noexcept(std::is_nothrow_copy_assignable::value);
+ constexpr storage_for& operator=(storage_for&& s)noexcept(std::is_nothrow_move_assignable::value);
+ constexpr storage_for& operator=(const_reference t)noexcept(std::is_nothrow_copy_assignable::value);
+ constexpr storage_for& operator=(rvalue_reference t)noexcept(std::is_nothrow_move_assignable::value);
+ constexpr void destroy(void)noexcept(std::is_nothrow_destructible::value);
+
+ constexpr operator reference(void)noexcept;
+ constexpr operator const_reference(void)const noexcept;
+ constexpr operator rvalue_reference(void)&& noexcept;
+
+ constexpr pointer operator->(void)noexcept;
+ constexpr const_pointer operator->(void)const noexcept;
+ constexpr reference operator*(void)noexcept;
+ constexpr const_reference operator*(void)const noexcept;
+
+ bool valid(void)const;
+ };
+
+}
+
+#include "storage_for.tpp"
+
+#endif
diff --git a/include/rexy/storage_for.tpp b/include/rexy/storage_for.tpp
new file mode 100644
index 0000000..5e0e53b
--- /dev/null
+++ b/include/rexy/storage_for.tpp
@@ -0,0 +1,123 @@
+/**
+ 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
+
+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
+ 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 m_storage;
+ }
+ template
+ constexpr storage_for::operator rvalue_reference(void)&& noexcept{
+ return reinterpret_cast(std::move(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
+ bool storage_for::valid(void)const{
+ return m_dirty;
+ }
+
+}
+
+#endif
diff --git a/src/ensure.cpp b/src/ensure.cpp
index 5ff17c5..b53ebcf 100644
--- a/src/ensure.cpp
+++ b/src/ensure.cpp
@@ -24,6 +24,7 @@
#include "rexy/source_location.hpp"
#include "rexy/demangle.hpp"
#include "rexy/debug_print.hpp"
+#include "rexy/storage_for.hpp"
#include "rexy/detail/binary_string_conv.hpp"
#include "rexy/detail/string_appender.hpp"