|
|
- #pragma once
- #include <type_traits>
- #include "gp/algorithm/move.hpp"
-
- namespace gp {
-
-
-
- template<typename F, typename ... Args>
- 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 <class>
- constexpr bool is_reference_wrapper_v = false;
- template <class U>
- constexpr bool is_reference_wrapper_v<std::reference_wrapper<U>> = true;
-
- template <class T, class Type, class T1, class... Args>
- constexpr decltype(auto) INVOKE(Type T::* f, T1&& t1, Args&&... args)
- {
- if constexpr (std::is_member_function_pointer_v<decltype(f)>) {
- if constexpr (std::is_base_of_v<T, std::decay_t<T1>>)
- return (gp::forward<T1>(t1).*f)(gp::forward<Args>(args)...);
- else if constexpr (is_reference_wrapper_v<std::decay_t<T1>>)
- return (t1.get().*f)(gp::forward<Args>(args)...);
- else
- return ((*gp::forward<T1>(t1)).*f)(gp::forward<Args>(args)...);
- } else {
- static_assert(std::is_member_object_pointer_v<decltype(f)>);
- static_assert(sizeof...(args) == 0);
- if constexpr (std::is_base_of_v<T, std::decay_t<T1>>)
- return gp::forward<T1>(t1).*f;
- else if constexpr (is_reference_wrapper_v<std::decay_t<T1>>)
- return t1.get().*f;
- else
- return (*gp::forward<T1>(t1)).*f;
- }
- }
-
- template <class F, class... Args>
- constexpr decltype(auto) INVOKE(F&& f, Args&&... args)
- {
- return gp::forward<F>(f)(gp::forward<Args>(args)...);
- }
- } // namespace detail
-
- template< class F, class... Args>
- constexpr std::invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
- noexcept(std::is_nothrow_invocable_v<F, Args...>)
- {
- return detail::INVOKE(gp::forward<F>(f), gp::forward<Args>(args)...);
- }
-
-
-
- template< class T >
- struct remove_cvref {
- typedef std::remove_cv_t<std::remove_reference_t<T>> type;
- };
-
- template< class T >
- using remove_cvref_t = typename remove_cvref<T>::type;
-
- template< class T >
- T* addressof(T& arg)
- {
- return reinterpret_cast<T*>(
- &const_cast<char&>(
- reinterpret_cast<const volatile char&>(arg)));
- }
-
- namespace detail {
- template <class T> constexpr T& FUN(T& t) noexcept { return t; }
- template <class T> void FUN(T&&) = delete;
- }
-
- template <class T>
- class reference_wrapper {
- public:
- // types
- typedef T type;
-
- // construct/copy/destroy
- template <class U, class = decltype(
- detail::FUN<T>(std::declval<U>()),
- std::enable_if_t<!std::is_same_v<reference_wrapper, gp::remove_cvref_t<U>>>()
- )>
- constexpr reference_wrapper(U&& u) noexcept(noexcept(detail::FUN<T>(gp::forward<U>(u))))
- : _ptr(gp::addressof(detail::FUN<T>(gp::forward<U>(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<T&, ArgTypes...>
- operator() ( ArgTypes&&... args ) const {
- return gp::invoke(get(), gp::forward<ArgTypes>(args)...);
- }
-
- private:
- T* _ptr;
- };
-
- // deduction guides
- template<class T>
- reference_wrapper(T&) -> reference_wrapper<T>;
-
- template<typename T>
- auto ref(T& vref) {
- return reference_wrapper<T>(vref);
- }
-
- template <class _DecayFunc>
- class __not_fn_imp {
- _DecayFunc __fd;
-
- public:
- __not_fn_imp() = delete;
-
- template <class ..._Args>
- 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 <class ..._Args>
- 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 <class ..._Args>
- 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 <class ..._Args>
- 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 <class _RawFunc,
- class = std::enable_if_t<!std::is_same<std::decay_t<_RawFunc>, __not_fn_imp>::value>>
- explicit __not_fn_imp(_RawFunc&& __rf)
- : __fd(gp::forward<_RawFunc>(__rf)) {}
-
- template <class _RawFunc>
- friend inline __not_fn_imp<std::decay_t<_RawFunc>> not_fn(_RawFunc&&);
- };
-
- template <class _RawFunc>
- inline __not_fn_imp<std::decay_t<_RawFunc>> not_fn(_RawFunc&& __fn) {
- return __not_fn_imp<std::decay_t<_RawFunc>>(gp::forward<_RawFunc>(__fn));
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
|