Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
std::not_fn(3)		      C++ Standard Libary		std::not_fn(3)

NAME
       std::not_fn - std::not_fn

Synopsis
	  Defined in header <functional>
	  template< class F >				 (1) (since C++17)
	  /*  unspecified */ not_fn( F&& f );		      (constexpr since
       C++20)
	  template< auto ConstFn >			 (2) (since C++26)
	  constexpr /* unspecified */ not_fn() noexcept;

	  1) Creates a forwarding call wrapper that returns  the  negation  of
       the callable
	  object it holds.
	  2)  Creates  a  forwarding call wrapper that returns the negation of
       the statically
	  determined callable target. The program is ill-formed	if ConstFn  is
       a null pointer
	  or null pointer-to-member.

Parameters
	  f	 -	the  object from which the Callable object held	by the
       wrapper is
		      constructed

Type requirements
	  -
	  std::decay_t<F> must meet the	requirements of	Callable and  MoveCon-
       structible.
	  -
	  std::is_constructible_v<std::decay_t<F>, F> is required to be	true.

Return value
	  1)  A	 function  object  of unspecified type T. It has the following
       members.

       std::not_fn return type

Member objects
	  The return type  of  std::not_fn  holds  a  member  object  of  type
       std::decay_t<F>.

	   Constructors

					 (since	C++17)
	  explicit T( F&& f );	     (1) (constexpr since C++20)
					 (exposition only*)
	  T( T&& f ) = default;	     (2) (since	C++17)
	  T( const T& f	) = default;

	  1) The constructor direct-non-list-initializes the member object (of
       type
	  std::decay_t<F>)   from  std::forward<F>(f).	Throws	any  exception
       thrown by the
	  constructor selected.
	  2) Because std::decay_t<F> is	required to be MoveConstructible,  the
       returned	call
	  wrapper  is  always  MoveConstructible,  and is CopyConstructible if
       std::decay_t<F> is
	  CopyConstructible.

	  The explicitly  defaulted  definitions  make	the  return  type  not
       (until C++20)
	  assignable.
	  It  is  unspecified  whether	these  constructors are	explicitly de-
       faulted	(since C++20)
	  and whether the return type is assignable.

Member function	operator()
	  template< class... Args >

	  auto operator()( Args&&... args ) &
	  ->					       decltype(!std::declval<
       (since
	      std::invoke_result_t<std::decay_t<F>&,		 Args...>>());
       C++17)
	  template<		  class...		 Args		     >
       (until
	  auto	     operator()(       Args&&...       args	 )	const&
       C++20)
	  -> decltype(!std::declval<

	      std::invoke_result_t<std::decay_t<F> const&,
	  Args...>>());
	  template< class... Args >

	  constexpr auto operator()( Args&&... args ) &
	      noexcept(/* see below */)
	  -> decltype(!std::invoke(
	      std::declval<std::decay_t<F>&>(),
	  std::declval<Args>()...));
       (since
	  template<		  class...		 Args		     >
       C++20)
	  constexpr auto operator()( Args&&... args ) const&
	      noexcept(/* see below */)
	  -> decltype(!std::invoke(

	      std::declval<std::decay_t<F> const&>(),
	  std::declval<Args>()...));				       (1)
	  template< class... Args >

	  auto operator()( Args&&... args ) &&
	  ->					       decltype(!std::declval<
       (since
	      std::invoke_result_t<std::decay_t<F>,		 Args...>>());
       C++17)
	  template<		   class...		  Args		     >
       (until
	  auto	    operator()(	     Args&&...	    args       )       const&&
       C++20)
	  -> decltype(!std::declval<

	      std::invoke_result_t<std::decay_t<F> const,
	  Args...>>());
	  template< class... Args >
									   (2)
	  constexpr auto operator()( Args&&... args ) &&
	      noexcept(/* see below */)
	  -> decltype(!std::invoke(
	      std::declval<std::decay_t<F>>(),
	  std::declval<Args>()...));
       (since
	  template<		   class...		  Args		     >
       C++20)
	  constexpr auto operator()( Args&&... args ) const&&
	      noexcept(/* see below */)
	  -> decltype(!std::invoke(

	      std::declval<std::decay_t<F> const>(),
	  std::declval<Args>()...));

	  Let fd be the	member object of type std::decay_t<F>.

	  1)	Equivalent    to     return	!std::invoke(fd,     std::for-
       ward<Args>(args)...);
	  2) Equivalent	to return !std::invoke(std::move(fd),
	  std::forward<Args>(args)...);
       (since C++17)
										 (un-
       til C++20)
	  While	 invoking the result, if the substitution into the return type
       of
	  the originally selected operator() overload fails, another overload
	  may be selected.
	  1) Expression-equivalent to !std::invoke(fd,
	  std::forward<Args>(args)...)
	  2) Expression-equivalent to !std::invoke(std::move(fd),
	  std::forward<Args>(args)...)
       (since C++20)

	  While	invoking the result, if	the substitution into the return  type
       of
	  the originally selected operator() overload fails, the invocation is
	  ill-formed, which can	also be	a substitution failure.

	  2) A value of	the following type.

       std::not_fn stateless return type

	  The  return  type  is	a CopyConstructible stateless class. It	is un-
       specified whether
	  the return type is assignable.

Member function	operator()
	  template< class... Args >

	  constexpr auto operator()( Args&&... args ) const		(since
       C++26)
	      noexcept(/* see below */)

	  -> decltype(!std::invoke(ConstFn, std::declval<Args>()...));

	  Expression-equivalent	    to	   !std::invoke(ConstFn,     std::for-
       ward<Args>(args)...).

Exceptions
	  1) Throws no exceptions, unless the construction of fd throws.

Possible implementation
						(1) not_fn
	  namespace detail
	  {
	      template<class V,	class F, class... Args>
	      constexpr	bool negate_invocable_impl = false;
	      template<class F,	class... Args>
	      constexpr	bool negate_invocable_impl<std::void_t<decltype(
		  !std::invoke(std::declval<F>(),  std::declval<Args>()...))>,
       F, Args...> = true;

	      template<class F,	class... Args>
	      constexpr	bool 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::for-
       ward<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::for-
       ward<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::for-
       ward<Args>(args)...)))
		  {
		      return	   !std::invoke(std::move(f),	     std::for-
       ward<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::for-
       ward<Args>(args)...)))
		  {
		      return	    !std::invoke(std::move(f),	     std::for-
       ward<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>
		  constexpr auto operator()(Args&&... args) const
		      noexcept(noexcept(!std::invoke(ConstFn,	     std::for-
       ward<Args>(args)...)))
		      ->       decltype(!std::invoke(ConstFn,	     std::for-
       ward<Args>(args)...))
		  {
		      return	      !std::invoke(ConstFn,	     std::for-
       ward<Args>(args)...);
		  }
	      };
	  }

	  template<auto	ConstFn>
	  constexpr detail::stateless_not_fn<ConstFn> not_fn() noexcept
	  {
	      if constexpr (std::is_pointer_v<decltype(ConstFn)> ||
			    std::is_member_pointer_v<decltype(ConstFn)>)
		  static_assert(ConstFn	!= nullptr);

	      return {};
	  }

Notes
	  std::not_fn is intended to replace the C++03-era negators  std::not1
       and std::not2.

	  Feature-test macro  Value    Std			  Feature
			     201603L (C++17) std::not_fn(), (1)
	  __cpp_lib_not_fn   202306L (C++26) Allow passing callable objects as
       non-type
					     template	    arguments	    to
       std::not_fn, (2)

Example
       // Run this code

	#include <cassert>
	#include <functional>

	bool is_same(int a, int	b) noexcept
	{
	    return a ==	b;
	}

	struct S
	{
	    int	val;
	    bool is_same(int arg) const	noexcept { 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)
       == false
	    assert(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) == true
	    assert(differ(2, 2)	== false); //: !same(2,	2) == false

	#if __cpp_lib_not_fn >=	202306L
	    auto 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
	}

See also
	  not1			constructs custom std::unary_negate object
	  (deprecated in C++17)	(function template)
	  (removed in C++20)
	  not2			constructs custom std::binary_negate object
	  (deprecated in C++17)	(function template)
	  (removed in C++20)

http://cppreference.com		  2024.06.10			std::not_fn(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=std::not_fn&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help