#pragma once
#include
#include
#include "is_reference_wrapper.hpp"
template
struct invoke_impl {
template
static constexpr auto call(F&& f, Args&&... args)
noexcept(noexcept(static_cast(f)(static_cast(args)...)))
-> decltype(static_cast(f)(static_cast(args)...))
{ return static_cast(f)(static_cast(args)...); }
};
template
struct invoke_impl {
template
static constexpr auto get(T&& t) noexcept -> T&&
{ return static_cast(t); }
template
static constexpr auto get(T&& t) noexcept -> decltype(t.get())
{ return t.get(); }
template>,
class = std::enable_if_t>>
>
static constexpr auto get(T&& t)
noexcept(noexcept(*static_cast(t)))
-> decltype(*static_cast(t))
{ return *static_cast(t); }
template
static constexpr auto call(AA B::*pmf, T&& t, Args&&... args)
noexcept(noexcept(((get)(static_cast(t)).*pmf)(static_cast(args)...)))
-> decltype(((get)(static_cast(t)).*pmf)(static_cast(args)...))
{ return ((get)(static_cast(t)).*pmf)(static_cast(args)...); }
template
static constexpr auto call(A B::*pmd, T&& t)
noexcept(noexcept((get)(static_cast(t)).*pmd))
-> decltype((get)(static_cast(t)).*pmd)
{ return (get)(static_cast(t)).*pmd; }
};
template
constexpr auto invoke(F&& f, Args&&... args)
noexcept(noexcept(invoke_impl::call(
static_cast(f), static_cast(args)...)))
-> decltype(invoke_impl::call(
static_cast(f), static_cast(args)...))
{
return invoke_impl::call(
static_cast(f), static_cast(args)...);
}
template
constexpr R invoke(F&& f, Args&&... args)
noexcept(noexcept(invoke_impl::call(
static_cast(f), static_cast(args)...)) &&
(std::is_void_v || std::is_nothrow_convertible_v))
{
if constexpr (!std::is_void_v)
return invoke_impl::call(
static_cast(f), static_cast(args)...);
else
invoke_impl::call(
static_cast(f), static_cast(args)...);
}