21using transform_param_t = std::conditional_t<std::is_trivially_copyable_v<T>, T, std::add_rvalue_reference_t<T>>;
25constexpr R invoke_r(F&& f, Args&&... args)
noexcept(std::is_nothrow_invocable_r_v<R, F, Args...>) {
67 using cv =
typename signature::template cvref<T>;
70 static constexpr bool noex = signature::is_noexcept;
73 static constexpr bool is_invocable_using =
74 noex ? std::is_nothrow_invocable_r_v<R, T..., Args...> : std::is_invocable_r_v<R, T..., Args...>;
76 using fwd_t = R(
storage, transform_param_t<Args>...)
noexcept(noex);
77 fwd_t* fptr_ =
nullptr;
83 requires std::is_function_v<F> && is_invocable_using<F>
84 : fptr_([](
storage fn_, transform_param_t<Args>... args)
noexcept(noex) -> R {
85 if constexpr (std::is_void_v<R>) get<F>(fn_)(
static_cast<decltype(args)
>(args)...);
86 else return get<F>(fn_)(
static_cast<decltype(args)
>(args)...);
90 template <
class F,
class T = std::remove_reference_t<F>>
92 requires(!std::is_same_v<std::remove_cvref_t<F>,
function_ref> && !std::is_member_pointer_v<T>
93 && is_invocable_using<cvref<T>>)
94 : fptr_([](
storage fn_, transform_param_t<Args>... args)
noexcept(noex) -> R {
95 cvref<T> obj = *get<T>(fn_);
96 if constexpr (std::is_void_v<R>) obj(
static_cast<decltype(args)
>(args)...);
97 else return obj(
static_cast<decltype(args)
>(args)...);
99 obj_(std::addressof(f)) {}
106 requires(!std::is_same_v<std::remove_cvref_t<T>,
function_ref> && !std::is_pointer_v<T> && !is_nontype_v<T>)
111 requires is_invocable_using<
decltype(f)>
112 : fptr_([](
storage, transform_param_t<Args>... args)
noexcept(noex) -> R {
113 return invoke_r<R>(f,
static_cast<decltype(args)
>(args)...);
115 using F =
decltype(f);
116 if constexpr (std::is_pointer_v<F> or std::is_member_pointer_v<F>)
117 static_assert(f !=
nullptr,
"NTTP callable must be usable");
120 template <auto f,
class U,
class T = std::remove_reference_t<U>>
122 requires(!std::is_rvalue_reference_v<U &&> && is_invocable_using<
decltype(f), cvref<T>>)
123 : fptr_([](
storage this_, transform_param_t<Args>... args)
noexcept(noex) -> R {
124 cvref<T> obj = *get<T>(this_);
125 return invoke_r<R>(f, obj,
static_cast<decltype(args)
>(args)...);
127 obj_(std::addressof(obj)) {
128 using F =
decltype(f);
129 if constexpr (std::is_pointer_v<F> or std::is_member_pointer_v<F>)
130 static_assert(f !=
nullptr,
"NTTP callable must be usable");
133 template <auto f,
class T>
135 requires is_invocable_using<
decltype(f),
decltype(obj)>
136 : fptr_([](
storage this_, transform_param_t<Args>... args)
noexcept(noex) -> R {
137 return invoke_r<R>(f, get<cv<T>>(this_),
static_cast<decltype(args)
>(args)...);
140 using F =
decltype(f);
141 if constexpr (std::is_pointer_v<F> or std::is_member_pointer_v<F>)
142 static_assert(f !=
nullptr,
"NTTP callable must be usable");
145 constexpr R operator()(Args... args)
const noexcept(noex) {
return fptr_(obj_, std::forward<Args>(args)...); }