libstdc++: Fix std::not_fn perfect forwarding [PR111327]
The previous patch fixed perfect forwarding in std::bind_front. This patch fixes the same issue in std::not_fn. PR libstdc++/111327 libstdc++-v3/ChangeLog: * include/std/functional (_GLIBCXX_NOT_FN_CALL_OP): Also define a deleted fallback operator() overload. Constrain both the enabled and deleted overloads accordingly. * testsuite/20_util/function_objects/not_fn/111327.cc: New test.
This commit is contained in:
parent
4289f6ceef
commit
52f65d17c8
2 changed files with 37 additions and 2 deletions
|
@ -1061,7 +1061,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
// forwarding _M_fn and the function arguments with the same qualifiers,
|
||||
// and deducing the return type and exception-specification.
|
||||
#define _GLIBCXX_NOT_FN_CALL_OP( _QUALS ) \
|
||||
template<typename... _Args> \
|
||||
template<typename... _Args, \
|
||||
typename = enable_if_t<__is_invocable<_Fn _QUALS, _Args...>::value>> \
|
||||
_GLIBCXX20_CONSTEXPR \
|
||||
decltype(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>()) \
|
||||
operator()(_Args&&... __args) _QUALS \
|
||||
|
@ -1070,7 +1071,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{ \
|
||||
return !std::__invoke(std::forward< _Fn _QUALS >(_M_fn), \
|
||||
std::forward<_Args>(__args)...); \
|
||||
}
|
||||
} \
|
||||
\
|
||||
template<typename... _Args, \
|
||||
typename = enable_if_t<!__is_invocable<_Fn _QUALS, _Args...>::value>> \
|
||||
void operator()(_Args&&... __args) _QUALS = delete;
|
||||
|
||||
_GLIBCXX_NOT_FN_CALL_OP( & )
|
||||
_GLIBCXX_NOT_FN_CALL_OP( const & )
|
||||
_GLIBCXX_NOT_FN_CALL_OP( && )
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// PR libstdc++/111327 - std::bind_front (and std::not_fn) doesn't always
|
||||
// perfectly forward according to value category of the call wrapper object
|
||||
// { dg-do compile { target c++17 } }
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
struct F {
|
||||
void operator()(...) & = delete;
|
||||
bool operator()(...) const &;
|
||||
};
|
||||
|
||||
struct G {
|
||||
void operator()(...) && = delete;
|
||||
bool operator()(...) const &&;
|
||||
};
|
||||
|
||||
int main() {
|
||||
auto f = std::not_fn(F{});
|
||||
f(); // { dg-error "deleted" }
|
||||
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" }
|
||||
std::move(std::as_const(g))();
|
||||
}
|
Loading…
Add table
Reference in a new issue