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