123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- #ifndef __GBLIBCPP_FUNCTIONAL__
- #define __GBLIBCPP_FUNCTIONAL__
- #include <bits/fwd_functional>
- #include <cstddef>
- #include <memory>
- #include <new>
- #include <utility>
- #include <type_traits>
- namespace std {
- template <typename Func, typename... Args>
- constexpr auto invoke(Func&& func, Args&&... args)
- noexcept(std::is_nothrow_invocable_v<Func, Args...>)
- -> std::enable_if_t<std::is_invocable_v<Func, Args...>,
- std::invoke_result_t<Func, Args...>>
- {
- return __helpers::INVOKE(std::forward<Func>(func), std::forward<Args>(args)...);
- }
- template <typename R, typename Func, typename... Args>
- constexpr auto invoke_r(Func&& func, Args&&... args)
- noexcept(std::is_nothrow_invocable_r_v<R, Func, Args...>)
- -> std::enable_if_t<std::is_invocable_r_v<R, Func, Args...>, R>
- {
- return __helpers::INVOKE_R<R>(std::forward<Func>(func), std::forward<Args>(args)...);
- }
- namespace __helpers {
- template <typename T> constexpr void __reference_wrapper_check(T&) noexcept {}
- template <typename T> void __reference_wrapper_check(T&&) = delete;
- } // namespace __helpers
- template <typename T>
- class reference_wrapper {
- private:
- T* _ptr;
- template <typename Ref, typename =
- decltype(__helpers::__reference_wrapper_check<T>(std::declval<Ref>()))>
- struct __check_reference_valid
- : public bool_constant<!std::is_same_v<reference_wrapper, std::decay_t<Ref>>> {};
- public:
- using type = T;
- constexpr T& get(void) const noexcept { return *_ptr; }
- constexpr operator T&(void) const noexcept { return *_ptr; }
- template <typename U, std::enable_if_t<__check_reference_valid<U>::value, bool> = true>
- constexpr reference_wrapper(U&& ref)
- noexcept(noexcept(__helpers::__reference_wrapper_check<T>(std::declval<U>())))
- : _ptr(std::addressof(ref)) {}
- constexpr reference_wrapper(const reference_wrapper& val) noexcept
- {
- _ptr = val._ptr;
- }
- constexpr reference_wrapper& operator=(const reference_wrapper& val) noexcept = default;
- // TODO: std::invoke_result_t
- template <typename... Args>
- constexpr invoke_result_t<type&, Args...>
- operator()(Args&&... args) const noexcept(is_nothrow_invocable_v<type&, Args...>)
- {
- return std::invoke(get(), std::forward<Args>(args)...);
- }
- };
- template <typename T>
- reference_wrapper(T&) -> reference_wrapper<T>;
- namespace __inner {
- template <typename Ret, typename... Args>
- class _function_base {
- public:
- virtual constexpr ~_function_base() = default;
- virtual constexpr Ret operator()(Args... args) const = 0;
- virtual constexpr void copy_to(_function_base* func) = 0;
- virtual constexpr void move_to(_function_base* func) = 0;
- virtual explicit constexpr operator bool(void) const = 0;
- };
- template <typename FuncLike, typename Ret, typename... Args>
- class _function : public _function_base<Ret, Args...> {
- private:
- using __enable = std::enable_if_t<
- std::is_invocable_r_v<Ret, std::decay_t<FuncLike>, Args...>
- >;
- FuncLike func;
- public:
- constexpr _function(const FuncLike& _func) : func(_func) {}
- constexpr _function(FuncLike&& _func) : func(std::move(_func)) {}
- constexpr Ret operator()(Args... args) const override
- {
- return std::invoke(func, std::forward<Args>(args)...);
- }
- constexpr void copy_to(_function_base<Ret, Args...>* dst) override
- {
- new (reinterpret_cast<_function*>(dst)) _function(*this);
- }
- constexpr void move_to(_function_base<Ret, Args...>* dst) override
- {
- new (reinterpret_cast<_function*>(dst)) _function(std::move(*this));
- }
- constexpr explicit operator bool(void) const override
- {
- return true;
- }
- };
- template <typename Ret, typename... Args>
- class _function<nullptr_t, Ret, Args...> : public _function_base<Ret, Args...> {
- public:
- [[noreturn]] Ret operator()(Args...) const override
- {
- // TODO: exception
- *((int*)(100^100)) = 1; // triggers access to null pointer
- for (;;);
- }
- constexpr void copy_to(_function_base<Ret, Args...>* dst) override
- {
- new (reinterpret_cast<_function*>(dst)) _function(*this);
- }
- constexpr void move_to(_function_base<Ret, Args...>* dst) override
- {
- new (reinterpret_cast<_function*>(dst)) _function(std::move(*this));
- }
- constexpr explicit operator bool(void) const override
- {
- return false;
- }
- };
- } // namespace __inner
- template <typename Ret, typename... Args>
- class function<Ret(Args...)> {
- public:
- using result_type = Ret;
- private:
- static constexpr std::size_t STACK_ALLOCATED_SIZE = 12;
- char _data[STACK_ALLOCATED_SIZE];
- using fb_t = __inner::_function_base<Ret, Args...>;
- constexpr fb_t* _f(void) const
- {
- return (fb_t*)_data;
- }
- constexpr void _clear(void)
- {
- _f()->~_function_base();
- }
- public:
- constexpr function() noexcept
- {
- new (_f()) __inner::_function<nullptr_t, Ret, Args...>();
- }
- constexpr function(nullptr_t) noexcept : function() {}
- constexpr function(const function& func)
- {
- func._f()->copy_to(_f());
- }
- constexpr function(function&& func) noexcept
- {
- func._f()->move_to(_f());
- }
- template <typename FuncLike, std::enable_if_t
- <
- // TODO: check its behavior for nullptr
- std::is_invocable_r_v<Ret, std::decay_t<FuncLike>, Args...>
- && (sizeof(std::decay_t<FuncLike>) <= STACK_ALLOCATED_SIZE - sizeof(void*))
- && !std::is_same_v<std::decay_t<FuncLike>, function>
- , bool> = true
- >
- constexpr function(FuncLike&& func)
- {
- new (_f()) __inner::_function<std::decay_t<FuncLike>, Ret, Args...>(std::forward<FuncLike>(func));
- }
- constexpr ~function()
- {
- _clear();
- }
- constexpr Ret operator()(Args... args) const
- {
- return (*_f())(std::forward<Args>(args)...);
- }
- explicit operator bool(void) const noexcept
- {
- return !!*_f();
- }
- function& operator=(function&& rhs)
- {
- _clear();
- rhs._f()->move_to(_f());
- return *this;
- }
- void swap(function& other) noexcept
- {
- function tmp(std::move(other));
- other = std::move(*this);
- *this = std::move(tmp);
- }
- function& operator=(const function& rhs)
- {
- _clear();
- rhs._f()->copy_to(_f());
- return *this;
- }
- function& operator=(nullptr_t) noexcept
- {
- _clear();
- new (_f()) __inner::_function<nullptr_t, Ret, Args...>();
- return *this;
- }
- template <typename FuncLike, std::enable_if_t
- <
- std::is_same_v<
- Ret,
- decltype(std::declval<std::decay_t<FuncLike>>()(std::declval<Args>()...))
- >
- && (sizeof(std::decay_t<FuncLike>) <= sizeof(_data))
- && !std::is_same_v<std::decay_t<FuncLike>, function>
- , bool> = true
- >
- function& operator=(FuncLike&& func)
- {
- function{std::forward<FuncLike>(func)}.swap(*this);
- return *this;
- }
- template <typename FuncLike>
- function& operator=(std::reference_wrapper<FuncLike> func) noexcept
- {
- function{func}.swap(*this);
- return *this;
- }
- };
- template <typename Ret, typename... Args>
- bool operator==(const std::function<Ret(Args...)>& func, std::nullptr_t) noexcept
- {
- return !func;
- }
- template <typename Ret, typename... Args>
- void swap(std::function<Ret(Args...)>& lhs, std::function<Ret(Args...)>& rhs) noexcept
- {
- return lhs.swap(rhs);
- }
- template <typename T>
- constexpr std::reference_wrapper<T> ref(T& t) noexcept
- {
- return std::reference_wrapper<T>((t));
- }
- template <typename T>
- constexpr std::reference_wrapper<T>
- ref(std::reference_wrapper<T> t) noexcept
- {
- return t;
- }
- template <typename T>
- constexpr std::reference_wrapper<const T> cref(const T& t) noexcept
- {
- return std::reference_wrapper<const T>((t));
- }
- template <typename T>
- constexpr std::reference_wrapper<const T>
- cref(std::reference_wrapper<T> t) noexcept
- {
- return t;
- }
- // Comparators
- template <typename T = void>
- struct less {
- constexpr bool operator()(const T& lhs, const T& rhs) const
- { return lhs < rhs; }
- };
- template <>
- struct less<void> {
- template <typename T, typename U>
- constexpr auto operator()(T&& lhs, U&& rhs) const
- -> decltype(std::forward<T>(lhs) < std::forward<U>(rhs))
- { return std::forward<T>(lhs) < std::forward<U>(rhs); }
- };
- template <typename T = void>
- struct greater {
- constexpr bool operator()(const T& lhs, const T& rhs) const
- { return lhs > rhs; }
- };
- template <>
- struct greater<void> {
- template <typename T, typename U>
- constexpr auto operator()(T&& lhs, U&& rhs) const
- -> decltype(std::forward<T>(lhs) > std::forward<U>(rhs))
- { return std::forward<T>(lhs) > std::forward<U>(rhs); }
- };
- } // namespace std
- #endif
|