1 // Copyright 2020 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_FUNCTIONAL_NOT_FN_H_ 6 #define BASE_FUNCTIONAL_NOT_FN_H_ 7 8 #include <functional> 9 #include <type_traits> 10 #include <utility> 11 12 namespace base { 13 14 namespace internal { 15 16 template <typename F> 17 struct NotFnImpl { 18 F f; 19 20 template <typename... Args> decltypeNotFnImpl21 constexpr decltype(auto) operator()(Args&&... args) & noexcept { 22 return !std::invoke(f, std::forward<Args>(args)...); 23 } 24 25 template <typename... Args> decltypeNotFnImpl26 constexpr decltype(auto) operator()(Args&&... args) const& noexcept { 27 return !std::invoke(f, std::forward<Args>(args)...); 28 } 29 30 template <typename... Args> decltypeNotFnImpl31 constexpr decltype(auto) operator()(Args&&... args) && noexcept { 32 return !std::invoke(std::move(f), std::forward<Args>(args)...); 33 } 34 35 template <typename... Args> decltypeNotFnImpl36 constexpr decltype(auto) operator()(Args&&... args) const&& noexcept { 37 return !std::invoke(std::move(f), std::forward<Args>(args)...); 38 } 39 }; 40 41 } // namespace internal 42 43 // Implementation of C++17's std::not_fn. 44 // 45 // Reference: 46 // - https://en.cppreference.com/w/cpp/utility/functional/not_fn 47 // - https://wg21.link/func.not.fn 48 template <typename F> not_fn(F && f)49constexpr internal::NotFnImpl<std::decay_t<F>> not_fn(F&& f) { 50 return {std::forward<F>(f)}; 51 } 52 53 } // namespace base 54 55 #endif // BASE_FUNCTIONAL_NOT_FN_H_ 56