|
|
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Old binders and adaptors | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
Defined in header <functional> | ||
template<class F> /* unspecified */ not_fn( F&& f); | (1) | (since C++17) (constexpr since C++20) |
template<auto ConstFn> constexpr/* unspecified */ not_fn()noexcept; | (2) | (since C++26) |
ConstFn
is a null pointer or null pointer-to-member.Contents |
f | - | the object from which theCallable object held by the wrapper is constructed |
Type requirements | ||
-std::decay_t<F> must meet the requirements ofCallable andMoveConstructible. | ||
-std::is_constructible_v<std::decay_t<F>, F> is required to betrue. |
T
. It has the following members.The return type ofstd::not_fn
holds a member object of typestd::decay_t<F>.
explicit T( F&& f); | (1) | (since C++17) (constexpr since C++20) (exposition only*) |
T( T&& f)=default; T(const T& f)=default; | (2) | (since C++17) |
The explicitly defaulted definitions make the return type not assignable. | (until C++20) |
It is unspecified whether these constructors are explicitly defaulted and whether the return type is assignable. | (since C++20) |
(1) | ||
template<class...Args> auto operator()( Args&&...args)& | (since C++17) (until C++20) | |
template<class...Args> constexprauto operator()( Args&&...args)& | (since C++20) | |
(2) | ||
template<class...Args> auto operator()( Args&&...args)&& | (since C++17) (until C++20) | |
template<class...Args> constexprauto operator()( Args&&...args)&& | (since C++20) | |
Letfd be the member object of typestd::decay_t<F>.
1) Equivalent toreturn!std::invoke(fd,std::forward<Args>(args)...); 2) Equivalent toreturn!std::invoke(std::move(fd),std::forward<Args>(args)...); While invoking the result, if the substitution into the return type of the originally selectedoperator() overload fails,another overload may be selected. | (since C++17) (until C++20) |
While invoking the result, if the substitution into the return type of the originally selectedoperator() overload fails, the invocation is ill-formed, which can also be asubstitution failure. | (since C++20) |
The return type is aCopyConstructible stateless class. It is unspecified whether the return type is assignable.
template<class...Args> constexprauto operator()( Args&&...args)const | (since C++26) | |
Expression-equivalent to!std::invoke(ConstFn,std::forward<Args>(args)...).
(1) not_fn |
---|
namespace detail{template<class V,class F,class...Args>constexprbool negate_invocable_impl=false;template<class F,class...Args>constexprbool negate_invocable_impl<std::void_t<decltype(!std::invoke(std::declval<F>(),std::declval<Args>()...))>, F, Args...>=true; template<class F,class...Args>constexprbool negate_invocable_v= negate_invocable_impl<void, F, Args...>; template<class F>struct not_fn_t{ F f; template<class...Args,std::enable_if_t<negate_invocable_v<F&, Args...>,int>=0>constexpr decltype(auto) operator()(Args&&...args)&noexcept(noexcept(!std::invoke(f,std::forward<Args>(args)...))){return!std::invoke(f,std::forward<Args>(args)...);} template<class...Args,std::enable_if_t<negate_invocable_v<const F&, Args...>,int>=0>constexpr decltype(auto) operator()(Args&&...args)const&noexcept(noexcept(!std::invoke(f,std::forward<Args>(args)...))){return!std::invoke(f,std::forward<Args>(args)...);} template<class...Args,std::enable_if_t<negate_invocable_v<F, Args...>,int>=0>constexpr decltype(auto) operator()(Args&&...args)&&noexcept(noexcept(!std::invoke(std::move(f),std::forward<Args>(args)...))){return!std::invoke(std::move(f),std::forward<Args>(args)...);} template<class...Args,std::enable_if_t<negate_invocable_v<const F, Args...>,int>=0>constexpr decltype(auto) operator()(Args&&...args)const&&noexcept(noexcept(!std::invoke(std::move(f),std::forward<Args>(args)...))){return!std::invoke(std::move(f),std::forward<Args>(args)...);} // Deleted overloads are needed since C++20// for preventing a non-equivalent but well-formed overload to be selected. template<class...Args,std::enable_if_t<!negate_invocable_v<F&, Args...>,int>=0>void operator()(Args&&...)&= delete; template<class...Args,std::enable_if_t<!negate_invocable_v<const F&, Args...>,int>=0>void operator()(Args&&...)const&= delete; template<class...Args,std::enable_if_t<!negate_invocable_v<F, Args...>,int>=0>void operator()(Args&&...)&&= delete; template<class...Args,std::enable_if_t<!negate_invocable_v<const F, Args...>,int>=0>void operator()(Args&&...)const&&= delete;};} template<class F>constexpr detail::not_fn_t<std::decay_t<F>> not_fn(F&& f){return{std::forward<F>(f)};} |
(2) not_fn |
namespace detail{template<auto ConstFn>struct stateless_not_fn{template<class...Args>constexprauto operator()(Args&&...args)constnoexcept(noexcept(!std::invoke(ConstFn,std::forward<Args>(args)...)))-> decltype(!std::invoke(ConstFn,std::forward<Args>(args)...)){return!std::invoke(ConstFn,std::forward<Args>(args)...);}};} template<auto ConstFn>constexpr detail::stateless_not_fn<ConstFn> not_fn()noexcept{ifconstexpr(std::is_pointer_v<decltype(ConstFn)>||std::is_member_pointer_v<decltype(ConstFn)>) static_assert(ConstFn!= nullptr); return{};} |
std::not_fn
is intended to replace the C++03-era negatorsstd::not1 andstd::not2.
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_lib_not_fn | 201603L | (C++17) | std::not_fn() ,(1) |
202306L | (C++26) | Allow passing callable objects as constant template arguments tostd::not_fn ,(2) |
#include <cassert>#include <functional> bool is_same(int a,int b)noexcept{return a== b;} struct S{int val;bool is_same(int arg)constnoexcept{return val== arg;}}; int main(){// Using with a free function:auto is_differ= std::not_fn(is_same);assert(is_differ(8,8)==false);// equivalent to: !is_same(8, 8) == falseassert(is_differ(6,9)==true);// equivalent to: !is_same(8, 0) == true // Using with a member function:auto member_differ= std::not_fn(&S::is_same);assert(member_differ(S{3},3)==false);//: S tmp{6}; !tmp.is_same(6) == false // Noexcept-specification is preserved: static_assert(noexcept(is_differ)==noexcept(is_same)); static_assert(noexcept(member_differ)==noexcept(&S::is_same)); // Using with a function object:auto same=[](int a,int b){return a== b;};auto differ= std::not_fn(same);assert(differ(1,2)==true);//: !same(1, 2) == trueassert(differ(2,2)==false);//: !same(2, 2) == false #if __cpp_lib_not_fn >= 202306Lauto is_differ_cpp26= std::not_fn<is_same>();assert(is_differ_cpp26(8,8)==false);assert(is_differ_cpp26(6,9)==true); auto member_differ_cpp26= std::not_fn<&S::is_same>();assert(member_differ_cpp26(S{3},3)==false); auto differ_cpp26= std::not_fn<same>(); static_assert(differ_cpp26(1,2)==true); static_assert(differ_cpp26(2,2)==false);#endif}
(deprecated in C++17)(removed in C++20) | constructs customstd::unary_negate object (function template)[edit] |
(deprecated in C++17)(removed in C++20) | constructs customstd::binary_negate object (function template)[edit] |