diff --git a/libstdc++-v3/include/bits/funcwrap.h b/libstdc++-v3/include/bits/funcwrap.h index 70ecfd93e369..1a81c9a9b466 100644 --- a/libstdc++-v3/include/bits/funcwrap.h +++ b/libstdc++-v3/include/bits/funcwrap.h @@ -538,14 +538,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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 consteval auto __deduce_funcref() { if constexpr (is_member_object_pointer_v<_Fn>) - // TODO Consider reporting issue to make this noexcept - return static_cast(*)()>(nullptr); - else + { + if constexpr (is_invocable_v<_Fn, _Tr>) + // TODO Consider reporting issue to make this noexcept + return static_cast(*)()>(nullptr); + } + else if constexpr (requires { typename __skip_first_arg<_Fn>::type; }) return static_cast<__skip_first_arg<_Fn>::type*>(nullptr); } } // namespace __polyfunc @@ -562,11 +566,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION requires is_function_v<_Fn> function_ref(nontype_t<__f>) -> function_ref<_Fn>; - template - requires is_member_pointer_v<_Fn> || is_function_v> + template())> + requires (!is_void_v<_SignaturePtr>) function_ref(nontype_t<__f>, _Tp&&) - -> function_ref< - remove_pointer_t())>>; + -> function_ref>; #endif // __glibcxx_function_ref diff --git a/libstdc++-v3/testsuite/20_util/function_ref/deduction.cc b/libstdc++-v3/testsuite/20_util/function_ref/deduction.cc index 2940b8769541..6ed2b4e5712e 100644 --- a/libstdc++-v3/testsuite/20_util/function_ref/deduction.cc +++ b/libstdc++-v3/testsuite/20_util/function_ref/deduction.cc @@ -10,6 +10,13 @@ using std::function_ref; int i = 0; +template + concept deductible = requires (Args&... args) + { std::function_ref(std::nontype, args...); }; + +static_assert( !deductible<1> ); +static_assert( !deductible<1, int> ); + void f0(); void f0n() noexcept; @@ -21,6 +28,8 @@ static_assert( is_same_v)), function_ref> ); static_assert( is_same_v)), function_ref> ); +static_assert( !deductible ); +static_assert( !deductible ); void f1(int); void f1n(int) noexcept; @@ -37,6 +46,8 @@ static_assert( is_same_v, i)), function_ref> ); static_assert( is_same_v, i)), function_ref> ); +static_assert( !deductible ); +static_assert( !deductible ); void f2(int*, int); void f2n(int*, int) noexcept; @@ -53,6 +64,8 @@ static_assert( is_same_v, &i)), function_ref> ); static_assert( is_same_v, &i)), function_ref> ); +static_assert( !deductible ); +static_assert( !deductible ); struct S { @@ -68,6 +81,9 @@ struct S int fcl(float) const&; int fcln(float) const& noexcept; + + int fr(int) &&; + int frn(int) && noexcept; }; S s{}; const S cs{}; @@ -80,16 +96,23 @@ static_assert( is_same_v, &s)), function_ref> ); static_assert( is_same_v, &cs)), function_ref> ); +static_assert( !deductible<&S::mem, int> ); static_assert( is_same_v, s)), function_ref> ); static_assert( is_same_v, &s)), function_ref> ); +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, &s)), function_ref> ); static_assert( is_same_v, s)), function_ref> ); +static_assert( !deductible<&S::fc, char*> ); +static_assert( !deductible<&S::fcn, char*> ); static_assert( is_same_v, &s)), function_ref> ); @@ -101,3 +124,8 @@ static_assert( is_same_v, s)), static_assert( is_same_v, &s)), function_ref> ); +static_assert( !deductible<&S::fr, char*> ); +static_assert( !deductible<&S::frn, char*> ); +static_assert( !deductible<&S::fr, S> ); +static_assert( !deductible<&S::frn, S> ); +