xref: /llvm-project/libcxx/include/__functional/not_fn.h (revision c91d805e6627987bec8ec34ea67c1e8240940039)
1050b064fSChristopher Di Bella // -*- C++ -*-
2050b064fSChristopher Di Bella //===----------------------------------------------------------------------===//
3050b064fSChristopher Di Bella //
4050b064fSChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5050b064fSChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information.
6050b064fSChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7050b064fSChristopher Di Bella //
8050b064fSChristopher Di Bella //===----------------------------------------------------------------------===//
9050b064fSChristopher Di Bella 
10050b064fSChristopher Di Bella #ifndef _LIBCPP___FUNCTIONAL_NOT_FN_H
11050b064fSChristopher Di Bella #define _LIBCPP___FUNCTIONAL_NOT_FN_H
12050b064fSChristopher Di Bella 
13050b064fSChristopher Di Bella #include <__config>
14050b064fSChristopher Di Bella #include <__functional/invoke.h>
154d81a46fSArthur O'Dwyer #include <__functional/perfect_forward.h>
1679702f7fSIan Anderson #include <__type_traits/decay.h>
1779702f7fSIan Anderson #include <__type_traits/enable_if.h>
1879702f7fSIan Anderson #include <__type_traits/is_constructible.h>
19*c91d805eSJakub Mazurkiewicz #include <__type_traits/is_member_pointer.h>
20*c91d805eSJakub Mazurkiewicz #include <__type_traits/is_pointer.h>
21ea2206d7SArthur O'Dwyer #include <__utility/forward.h>
22050b064fSChristopher Di Bella 
23050b064fSChristopher Di Bella #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24050b064fSChristopher Di Bella #  pragma GCC system_header
25050b064fSChristopher Di Bella #endif
26050b064fSChristopher Di Bella 
27050b064fSChristopher Di Bella _LIBCPP_BEGIN_NAMESPACE_STD
28050b064fSChristopher Di Bella 
294f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 17
30050b064fSChristopher Di Bella 
31f599e7a7SLouis Dionne struct __not_fn_op {
32050b064fSChristopher Di Bella   template <class... _Args>
339783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 auto operator()(_Args&&... __args) const
3477a00c0dSLouis Dionne       noexcept(noexcept(!std::invoke(std::forward<_Args>(__args)...)))
359783f28cSLouis Dionne           -> decltype(!std::invoke(std::forward<_Args>(__args)...)) {
369783f28cSLouis Dionne     return !std::invoke(std::forward<_Args>(__args)...);
379783f28cSLouis Dionne   }
38050b064fSChristopher Di Bella };
39050b064fSChristopher Di Bella 
40f599e7a7SLouis Dionne template <class _Fn>
41f599e7a7SLouis Dionne struct __not_fn_t : __perfect_forward<__not_fn_op, _Fn> {
42f599e7a7SLouis Dionne   using __perfect_forward<__not_fn_op, _Fn>::__perfect_forward;
43f599e7a7SLouis Dionne };
44f599e7a7SLouis Dionne 
459783f28cSLouis Dionne template <class _Fn,
469783f28cSLouis Dionne           class = enable_if_t< is_constructible_v<decay_t<_Fn>, _Fn> && is_move_constructible_v<decay_t<_Fn>> >>
479783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 auto not_fn(_Fn&& __f) {
4877a00c0dSLouis Dionne   return __not_fn_t<decay_t<_Fn>>(std::forward<_Fn>(__f));
49050b064fSChristopher Di Bella }
50050b064fSChristopher Di Bella 
514f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 17
52050b064fSChristopher Di Bella 
53*c91d805eSJakub Mazurkiewicz #if _LIBCPP_STD_VER >= 26
54*c91d805eSJakub Mazurkiewicz 
55*c91d805eSJakub Mazurkiewicz template <auto _Fn>
56*c91d805eSJakub Mazurkiewicz struct __nttp_not_fn_t {
57*c91d805eSJakub Mazurkiewicz   template <class... _Args>
58*c91d805eSJakub Mazurkiewicz   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const
59*c91d805eSJakub Mazurkiewicz       noexcept(noexcept(!std::invoke(_Fn, std::forward<_Args>(__args)...)))
60*c91d805eSJakub Mazurkiewicz           -> decltype(!std::invoke(_Fn, std::forward<_Args>(__args)...)) {
61*c91d805eSJakub Mazurkiewicz     return !std::invoke(_Fn, std::forward<_Args>(__args)...);
62*c91d805eSJakub Mazurkiewicz   }
63*c91d805eSJakub Mazurkiewicz };
64*c91d805eSJakub Mazurkiewicz 
65*c91d805eSJakub Mazurkiewicz template <auto _Fn>
66*c91d805eSJakub Mazurkiewicz [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr auto not_fn() noexcept {
67*c91d805eSJakub Mazurkiewicz   if constexpr (using _Ty = decltype(_Fn); is_pointer_v<_Ty> || is_member_pointer_v<_Ty>)
68*c91d805eSJakub Mazurkiewicz     static_assert(_Fn != nullptr, "f cannot be equal to nullptr");
69*c91d805eSJakub Mazurkiewicz   return __nttp_not_fn_t<_Fn>();
70*c91d805eSJakub Mazurkiewicz }
71*c91d805eSJakub Mazurkiewicz 
72*c91d805eSJakub Mazurkiewicz #endif // _LIBCPP_STD_VER >= 26
73*c91d805eSJakub Mazurkiewicz 
74050b064fSChristopher Di Bella _LIBCPP_END_NAMESPACE_STD
75050b064fSChristopher Di Bella 
76050b064fSChristopher Di Bella #endif // _LIBCPP___FUNCTIONAL_NOT_FN_H
77