/* ***************************************************************************** * kblib is a general utility library for C++14 and C++17, intended to provide * performant high-level abstractions and more expressive ways to do simple * things. * * Copyright (c) 2021 killerbee * * 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 . * ****************************************************************************/ /** * @file * @brief Provides utilities to enable safe and expressive memory management and * low-level memory manipulation. * * @author killerbee * @date 2019-2021 * @copyright GNU General Public Licence v3.0 */ #ifndef MEMORY_H #define MEMORY_H #include "algorithm.h" #include "tdecl.h" #include #include namespace KBLIB_NS { template ::value> struct null_construct { null_construct() noexcept(std::is_nothrow_default_constructible::value) : t{} {} T t; operator T&() noexcept { return t; } operator const T&() const noexcept { return t; } }; template struct null_construct : public T { null_construct() noexcept(std::is_nothrow_default_constructible::value) : T{} {} }; #if __cpp_nontype_template_parameter_auto template struct fun_ptr_deleter; template struct fun_ptr_deleter { auto operator()(Arg arg) const -> void { return FunPtr(arg); } }; #endif namespace detail_memory { template struct filter_deleter_pointer { using type = T*; }; template struct filter_deleter_pointer> { using type = typename std::remove_reference::type::pointer; }; template using filter_deleter_pointer_t = typename filter_deleter_pointer::type; template ::value and not std::is_final::value, bool = std::is_object::type>::value> struct as_base_class; template struct as_base_class { T base_; auto base() noexcept -> T& { return base_; } auto base() const noexcept -> const T& { return base_; } explicit operator T&() noexcept { return base(); } explicit operator const T&() const noexcept { return base(); } }; template struct as_base_class : T { auto base() noexcept -> T& { return *this; } auto base() const noexcept -> const T& { return *this; } using T::T; as_base_class(const T& t, enable_if_t::value, as_base_class*> = nullptr) // noexcept(std::is_nothrow_copy_constructible::value) : T(t) {} as_base_class(T&& t, enable_if_t::value, as_base_class*> = nullptr) // noexcept(std::is_nothrow_move_constructible::value) : T(std::move(t)) {} }; #if KBLIB_USE_CXX17 template struct as_base_class { using type = R(A) noexcept(E); type* base_; auto base() const noexcept -> type& { return *base_; } explicit operator type&() const noexcept { return base(); } }; #else template struct as_base_class { using type = R(A); type* base_; auto base() const noexcept -> type& { return *base_; } explicit operator type&() const noexcept { return base(); } }; #endif template struct as_base_class { std::reference_wrapper base_; auto base() noexcept -> T& { return base_; } auto base() const noexcept -> const T& { return base_; } explicit operator T&() noexcept { return base(); } explicit operator const T&() const noexcept { return base(); } }; struct noop_t { auto operator()() const noexcept -> void {} }; struct value_init {}; template struct rule_zero : as_base_class { template rule_zero(Args&&... args) : as_base_class(std::forward(args)...) {} }; template struct on_destroy : as_base_class , as_base_class { on_destroy() noexcept = default; on_destroy(const on_destroy&) noexcept( std::is_nothrow_copy_constructible::value and std::is_nothrow_copy_constructible::value) = default; on_destroy(on_destroy&&) noexcept( std::is_nothrow_move_constructible::value and std::is_nothrow_move_constructible::value) = default; on_destroy& operator=(const on_destroy&) noexcept( std::is_nothrow_copy_assignable::value and std::is_nothrow_copy_assignable::value) = default; on_destroy& operator=(on_destroy&&) noexcept( std::is_nothrow_move_assignable::value and std::is_nothrow_move_assignable::value) = default; using as_base_class::base; operator T&() noexcept { return base(); } operator const T&() const noexcept { return base(); } ~on_destroy() { (invoke)(static_cast(*this), static_cast(*this)); } }; } // namespace detail_memory template class live_ptr; template class live_wrapper { public: live_ptr ref(); live_ptr ref() const; live_ptr cref() const; T data; struct _destroy { auto operator()(std::vector&& self) const noexcept -> void { for (auto p : self) { if (p) { *p = nullptr; } } } }; null_construct< detail_memory::on_destroy, _destroy>> _observers{}; }; template class live_wrapper : public live_wrapper {}; namespace detail_memory { template struct template_param; template