mirror of git://gcc.gnu.org/git/gcc.git
libstdc++: Use deducing this in std::not_fn when available [PR111327]
Implement the perfect forwarding required by std::not_fn using deducing this when available, instead of needing 8 operator() overloads. This also fixes Jiang An's test from this PR which would be messy to fix in the old implementation. PR libstdc++/111327 libstdc++-v3/ChangeLog: * include/std/functional (_Not_fn::operator()) [_GLIBCXX_EXPLICIT_THIS_PARAMETER]: Define as a single overload using deducing this. * testsuite/20_util/function_objects/not_fn/111327.cc: Extend test. Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com> Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
This commit is contained in:
parent
101f968476
commit
756e32a160
|
|
@ -1056,6 +1056,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
_Not_fn(_Not_fn&& __fn) = default;
|
||||
~_Not_fn() = default;
|
||||
|
||||
#if _GLIBCXX_EXPLICIT_THIS_PARAMETER
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this
|
||||
template<typename _Self, typename... _Args>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
decltype(_S_not<__inv_res_t<__like_t<_Self, _Fn>, _Args...>>())
|
||||
operator()(this _Self&& __self, _Args&&... __args)
|
||||
noexcept(__is_nothrow_invocable<__like_t<_Self, _Fn>, _Args...>::value
|
||||
&& noexcept(_S_not<__inv_res_t<__like_t<_Self, _Fn>, _Args...>>()))
|
||||
{
|
||||
return !std::__invoke(__like_t<_Self, _Not_fn>(__self)._M_fn,
|
||||
std::forward<_Args>(__args)...);
|
||||
}
|
||||
# pragma GCC diagnostic pop
|
||||
#else
|
||||
// Macro to define operator() with given cv-qualifiers ref-qualifiers,
|
||||
// forwarding _M_fn and the function arguments with the same qualifiers,
|
||||
// and deducing the return type and exception-specification.
|
||||
|
|
@ -1081,6 +1096,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
_GLIBCXX_NOT_FN_CALL_OP( && )
|
||||
_GLIBCXX_NOT_FN_CALL_OP( const && )
|
||||
#undef _GLIBCXX_NOT_FN_CALL_OP
|
||||
#endif
|
||||
|
||||
private:
|
||||
_Fn _M_fn;
|
||||
|
|
|
|||
|
|
@ -15,15 +15,28 @@ struct G {
|
|||
bool operator()(...) const &&;
|
||||
};
|
||||
|
||||
struct Weird {
|
||||
void operator()();
|
||||
bool operator()() const { return true; }
|
||||
};
|
||||
|
||||
int main() {
|
||||
auto f = std::not_fn(F{});
|
||||
f(); // { dg-error "deleted" }
|
||||
f(); // { dg-error "no match" }
|
||||
std::move(f)();
|
||||
std::as_const(f)();
|
||||
std::move(std::as_const(f))();
|
||||
|
||||
auto g = std::not_fn(G{});
|
||||
g(); // { dg-error "deleted" }
|
||||
std::move(g)(); // { dg-error "deleted" }
|
||||
g(); // { dg-error "no match" }
|
||||
std::move(g)(); // { dg-error "no match" }
|
||||
std::move(std::as_const(g))();
|
||||
|
||||
auto h = std::not_fn(Weird{});
|
||||
h(); // { dg-error "no match" }
|
||||
}
|
||||
|
||||
// { dg-error "no type named 'type' in 'struct std::__invoke_result<" "" { target *-*-* } 0 }
|
||||
// { dg-error "no matching function for call to 'std::_Not_fn<Weird>" "" { target *-*-* } 0 }
|
||||
// { dg-error "could not convert 'std::declval<void>\\(\\)' from 'void' to 'bool'" "" { target *-*-* } 0 }
|
||||
// { dg-error "in argument to unary !" "" { target *-*-* } 0 }
|
||||
|
|
|
|||
Loading…
Reference in New Issue