#pragma once #include #include "gp/algorithm/move.hpp" namespace gp { template auto bind_front(F&& func, Args&&... arg_parent) { return [&](auto&&... argv){ return func(arg_parent..., argv...); }; } /* Code extrated from cppreference.com and the libc++ Library project, licensed under MIT license */ namespace detail { template constexpr bool is_reference_wrapper_v = false; template constexpr bool is_reference_wrapper_v> = true; template constexpr decltype(auto) INVOKE(Type T::* f, T1&& t1, Args&&... args) { if constexpr (std::is_member_function_pointer_v) { if constexpr (std::is_base_of_v>) return (gp::forward(t1).*f)(gp::forward(args)...); else if constexpr (is_reference_wrapper_v>) return (t1.get().*f)(gp::forward(args)...); else return ((*gp::forward(t1)).*f)(gp::forward(args)...); } else { static_assert(std::is_member_object_pointer_v); static_assert(sizeof...(args) == 0); if constexpr (std::is_base_of_v>) return gp::forward(t1).*f; else if constexpr (is_reference_wrapper_v>) return t1.get().*f; else return (*gp::forward(t1)).*f; } } template constexpr decltype(auto) INVOKE(F&& f, Args&&... args) { return gp::forward(f)(gp::forward(args)...); } } // namespace detail template< class F, class... Args> constexpr std::invoke_result_t invoke(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_v) { return detail::INVOKE(gp::forward(f), gp::forward(args)...); } template< class T > struct remove_cvref { typedef std::remove_cv_t> type; }; template< class T > using remove_cvref_t = typename remove_cvref::type; template< class T > T* addressof(T& arg) { return reinterpret_cast( &const_cast( reinterpret_cast(arg))); } namespace detail { template constexpr T& FUN(T& t) noexcept { return t; } template void FUN(T&&) = delete; } template class reference_wrapper { public: // types typedef T type; // construct/copy/destroy template (std::declval()), std::enable_if_t>>() )> constexpr reference_wrapper(U&& u) noexcept(noexcept(detail::FUN(gp::forward(u)))) : _ptr(gp::addressof(detail::FUN(gp::forward(u)))) {} reference_wrapper(const reference_wrapper&) noexcept = default; // assignment reference_wrapper& operator=(const reference_wrapper& x) noexcept = default; // access constexpr operator T& () const noexcept { return *_ptr; } constexpr T& get() const noexcept { return *_ptr; } template< class... ArgTypes > constexpr std::invoke_result_t operator() ( ArgTypes&&... args ) const { return gp::invoke(get(), gp::forward(args)...); } private: T* _ptr; }; // deduction guides template reference_wrapper(T&) -> reference_wrapper; template auto ref(T& vref) { return reference_wrapper(vref); } template class __not_fn_imp { _DecayFunc __fd; public: __not_fn_imp() = delete; template auto operator()(_Args&& ...__args) & noexcept(noexcept(!gp::invoke(__fd, gp::forward<_Args>(__args)...))) -> decltype( !gp::invoke(__fd, gp::forward<_Args>(__args)...)) { return !gp::invoke(__fd, gp::forward<_Args>(__args)...); } template auto operator()(_Args&& ...__args) && noexcept(noexcept(!gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...))) -> decltype( !gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...)) { return !gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...); } template auto operator()(_Args&& ...__args) const& noexcept(noexcept(!gp::invoke(__fd, gp::forward<_Args>(__args)...))) -> decltype( !gp::invoke(__fd, gp::forward<_Args>(__args)...)) { return !gp::invoke(__fd, gp::forward<_Args>(__args)...); } template auto operator()(_Args&& ...__args) const&& noexcept(noexcept(!gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...))) -> decltype( !gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...)) { return !gp::invoke(gp::move(__fd), gp::forward<_Args>(__args)...); } private: template , __not_fn_imp>::value>> explicit __not_fn_imp(_RawFunc&& __rf) : __fd(gp::forward<_RawFunc>(__rf)) {} template friend inline __not_fn_imp> not_fn(_RawFunc&&); }; template inline __not_fn_imp> not_fn(_RawFunc&& __fn) { return __not_fn_imp>(gp::forward<_RawFunc>(__fn)); } }