struct __skip_first_arg<_Ret(*)(_Arg, _Args...) noexcept(_Noex)>
{ using type = _Ret(_Args...) noexcept(_Noex); };
+ // Returns a function pointer to signature to be used with function_ref, or void.
template<typename _Fn, typename _Tr>
consteval auto
__deduce_funcref()
{
if constexpr (is_member_object_pointer_v<_Fn>)
- // TODO Consider reporting issue to make this noexcept
- return static_cast<invoke_result_t<_Fn, _Tr>(*)()>(nullptr);
- else
+ {
+ if constexpr (is_invocable_v<_Fn, _Tr>)
+ // TODO Consider reporting issue to make this noexcept
+ return static_cast<invoke_result_t<_Fn, _Tr>(*)()>(nullptr);
+ }
+ else if constexpr (requires { typename __skip_first_arg<_Fn>::type; })
return static_cast<__skip_first_arg<_Fn>::type*>(nullptr);
}
} // namespace __polyfunc
requires is_function_v<_Fn>
function_ref(nontype_t<__f>) -> function_ref<_Fn>;
- template<auto __f, typename _Tp, class _Fn = decltype(__f)>
- requires is_member_pointer_v<_Fn> || is_function_v<remove_pointer_t<_Fn>>
+ template<auto __f, typename _Tp,
+ typename _SignaturePtr =
+ decltype(__polyfunc::__deduce_funcref<decltype(__f), _Tp&>())>
+ requires (!is_void_v<_SignaturePtr>)
function_ref(nontype_t<__f>, _Tp&&)
- -> function_ref<
- remove_pointer_t<decltype(__polyfunc::__deduce_funcref<_Fn, _Tp&>())>>;
+ -> function_ref<remove_pointer_t<_SignaturePtr>>;
#endif // __glibcxx_function_ref
int i = 0;
+template<auto f, class... Args>
+ concept deductible = requires (Args&... args)
+ { std::function_ref(std::nontype<f>, args...); };
+
+static_assert( !deductible<1> );
+static_assert( !deductible<1, int> );
+
void f0();
void f0n() noexcept;
function_ref<void()>> );
static_assert( is_same_v<decltype(function_ref(nontype<f0n>)),
function_ref<void() noexcept>> );
+static_assert( !deductible<f0, char*> );
+static_assert( !deductible<f0n, char*> );
void f1(int);
void f1n(int) noexcept;
function_ref<void()>> );
static_assert( is_same_v<decltype(function_ref(nontype<f1n>, i)),
function_ref<void() noexcept>> );
+static_assert( !deductible<f1, char*> );
+static_assert( !deductible<f1n, char*> );
void f2(int*, int);
void f2n(int*, int) noexcept;
function_ref<void(int)>> );
static_assert( is_same_v<decltype(function_ref(nontype<f2n>, &i)),
function_ref<void(int) noexcept>> );
+static_assert( !deductible<f2, char*> );
+static_assert( !deductible<f2n, char*> );
struct S
{
int fcl(float) const&;
int fcln(float) const& noexcept;
+
+ int fr(int) &&;
+ int frn(int) && noexcept;
};
S s{};
const S cs{};
function_ref<int&()>> );
static_assert( is_same_v<decltype(function_ref(nontype<&S::mem>, &cs)),
function_ref<const int&()>> );
+static_assert( !deductible<&S::mem, int> );
static_assert( is_same_v<decltype(function_ref(nontype<&S::f>, s)),
function_ref<int()>> );
static_assert( is_same_v<decltype(function_ref(nontype<&S::fn>, &s)),
function_ref<int() noexcept>> );
+static_assert( !deductible<&S::f, char*> );
+static_assert( !deductible<&S::fn, char*> );
+static_assert( !deductible<&S::f, const S> );
+static_assert( !deductible<&S::fn, const S> );
static_assert( is_same_v<decltype(function_ref(nontype<&S::fc>, &s)),
function_ref<int(int)>> );
static_assert( is_same_v<decltype(function_ref(nontype<&S::fcn>, s)),
function_ref<int(int) noexcept>> );
+static_assert( !deductible<&S::fc, char*> );
+static_assert( !deductible<&S::fcn, char*> );
static_assert( is_same_v<decltype(function_ref(nontype<&S::fl>, &s)),
function_ref<int(int)>> );
static_assert( is_same_v<decltype(function_ref(nontype<&S::fcln>, &s)),
function_ref<int(float) noexcept>> );
+static_assert( !deductible<&S::fr, char*> );
+static_assert( !deductible<&S::frn, char*> );
+static_assert( !deductible<&S::fr, S> );
+static_assert( !deductible<&S::frn, S> );
+