General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

187 lines
5.4 KiB

#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));
}
/**
*********************************************************************************************
*/
}