/* This file is part of Fennix Kernel. Fennix Kernel 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. Fennix Kernel 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 Fennix Kernel. If not, see . */ #pragma once #include #include #include namespace std { template struct equal_to { bool operator()(const T &lhs, const T &rhs) const { return lhs == rhs; } }; template struct hash { size_t operator()(const Key &key) const { #if defined(a64) static_assert(sizeof(uintptr_t) == sizeof(uint64_t)); const uint64_t FNV_OFFSET_BASIS = 14695981039346656037ull; const uint64_t FNV_PRIME = 1099511628211ull; #elif defined(a32) static_assert(sizeof(uintptr_t) == sizeof(uint32_t)); const uint32_t FNV_OFFSET_BASIS = 2166136261u; const uint32_t FNV_PRIME = 16777619u; #else #error "Unsupported architecture" #endif const uint8_t *data = reinterpret_cast(&key); const size_t size = sizeof(Key); uintptr_t hash = FNV_OFFSET_BASIS; for (size_t i = 0; i < size; ++i) { hash ^= static_cast(data[i]); hash *= FNV_PRIME; } return static_cast(hash); } }; template class reference_wrapper; template class function; /* undefined */ template class function { private: class impl_base { public: virtual ~impl_base() = default; virtual R invoke(Args...) const = 0; #ifdef __GXX_RTTI virtual const std::type_info &target_type() const noexcept = 0; #endif virtual impl_base *clone() const = 0; }; template class impl : public impl_base { public: F _f; template impl(G &&f) : _f(std::forward(f)) { } R invoke(Args... args) const override { return _f(std::forward(args)...); } #ifdef __GXX_RTTI const std::type_info &target_type() const noexcept override { return typeid(F); } #endif impl_base *clone() const override { return new impl(_f); } }; impl_base *_ptr; public: using result_type = R; function() noexcept : _ptr(nullptr) { } function(std::nullptr_t) noexcept : _ptr(nullptr) { } function(const function &other) : _ptr(other._ptr) { } function(function &&other) noexcept : _ptr(other._ptr) { other._ptr = nullptr; } template function(F &&f) : _ptr(new impl(std::forward(f))) { } ~function() { delete _ptr; } function &operator=(const function &other) { if (this != &other) { delete _ptr; _ptr = other._ptr ? other._ptr->clone() : nullptr; } return *this; } function &operator=(function &&other) { if (this != &other) { delete _ptr; _ptr = other._ptr; other._ptr = nullptr; } return *this; } function &operator=(std::nullptr_t) noexcept { delete _ptr; _ptr = nullptr; return *this; } template function &operator=(F &&f) { delete _ptr; _ptr = new impl(std::forward(f)); return *this; } template function &operator=(std::reference_wrapper f) noexcept { delete _ptr; _ptr = new impl>(f); return *this; } void swap(function &other) noexcept { std::swap(_ptr, other._ptr); } explicit operator bool() const noexcept { return _ptr != nullptr; } R operator()(Args... args) const { return _ptr->invoke(std::forward(args)...); } #ifdef __GXX_RTTI const std::type_info &target_type() const noexcept { return _ptr ? _ptr->target_type() : typeid(void); } template T *target() noexcept { return _ptr && _ptr->target_type() == typeid(T) ? &static_cast *>(_ptr)->_f : nullptr; } template const T *target() const noexcept { return _ptr && _ptr->target_type() == typeid(T) ? &static_cast *>(_ptr)->_f : nullptr; } #endif }; template void swap(std::function &lhs, std::function &rhs) noexcept { lhs.swap(rhs); } template bool operator==(const std::function &f, std::nullptr_t) noexcept { return !f; } template struct less { constexpr bool operator()(const T &lhs, const T &rhs) const { return lhs < rhs; } }; }