std::experimental::not_fn(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… std::experimental::not_fn β€” a C++ Standard Library page, bestie

okay so picture this: you're deep in the std::experimental namespace (yes, that one), you've got a callable, and you literally just want the opposite of it. that's this function. it lives on the manual page std::experimental::not_fn(3) and it is, no cap, kind of iconic. πŸŽ€

✨ NAME ✨

std::experimental::not_fn β€” std::experimental::not_fn (she contains multitudes, but the name is the name)

✨ Synopsis ✨

she's defined in the header <experimental/functional>, and here's the whole vibe:

template< class F>                           (library fundamentals TS v2)
/*unspecified*/ not_fn( F&& f );

what she does, in one breath: creates a forwarding call wrapper that returns the complement of the callable object it holds. ✨ complement = the ! of it. the "not" of it. iykyk.

🌸 Parameters 🌸

  • f β€” the object from which the Callable object held by the wrapper is constructed 🫢

πŸ’– Return value πŸ’–

okay this part is a little wordy but stay with me, it's worth it.

Let FD be std::decay_t<F> and fd be an lvalue of type FD constructed from std::forward<F>(f).

not_fn returns a forwarding call wrapper fn of unspecified type such that fn(a1, a2, ..., aN) is equivalent to !INVOKE(fd, a1, ..., aN), where INVOKE is the operation described in Callable.

The returned call wrapper is always MoveConstructible, and is CopyConstructible if FD is CopyConstructible. slay. πŸ’…

πŸ¦‹ Remarks πŸ¦‹

bestie. listen. if fd is not Callable, or std::is_constructible<FD, F>::value is not true, the behavior is undefined. not "a little weird", not "probably fine" β€” undefined. don't do it. πŸ™ˆ

🌈 Exceptions 🌈

Throws no exceptions, unless the construction of fd throws. that's it, that's the whole drama. (the only thing that can ruin the vibe is fd's own constructor being messy.)

πŸ‘‘ Possible implementation πŸ‘‘

here's like, one way you could do it. it's giving "here's the blueprint, don't @ me":

namespace detail {
    template<class F>
    struct not_fn_t {
        F f;
        template<class... Args>
        auto operator()(Args&&... args)
            noexcept(noexcept(!std::invoke(f, std::forward<Args>(args)...)))
            -> decltype(!std::invoke(f, std::forward<Args>(args)...))
        {
            return !std::invoke(f, std::forward<Args>(args)...);
        }

        // cv-qualified overload for QoI
        template<class... Args>
        auto operator()(Args&&... args) const
            noexcept(noexcept(!std::invoke(f, std::forward<Args>(args)...)))
            -> decltype(!std::invoke(f, std::forward<Args>(args)...))
        {
            return !std::invoke(f, std::forward<Args>(args)...);
        }

        template<class... Args>
        auto operator()(Args&&... args) volatile
            noexcept(noexcept(!std::invoke(f, std::forward<Args>(args)...)))
            -> decltype(!std::invoke(f, std::forward<Args>(args)...))
        {
            return !std::invoke(f, std::forward<Args>(args)...);
        }
        template<class... Args>
        auto operator()(Args&&... args) const volatile
            noexcept(noexcept(!std::invoke(f, std::forward<Args>(args)...)))
            -> decltype(!std::invoke(f, std::forward<Args>(args)...))
        {
            return !std::invoke(f, std::forward<Args>(args)...);
        }
    };
}

template<class F>
detail::not_fn_t<std::decay_t<F>> not_fn(F&& f) { return { std::forward<F>(f) }; }

like, four cv-qualified operator() overloads because quality-of-implementation said so and honestly? she understood the assignment. ⭐

🧚 Notes 🧚

not_fn is intended to replace the C++03-era negators std::not1 and std::not2. yes, those old ones. they had their era, we're moving on, no hard feelings, periodt. πŸ’œ

πŸ“ See also πŸ“

  • not_fn (C++17) β€” creates a function object that returns the complement of the result of the function object it holds (function template) πŸ”₯

and that's the page, bestie!! source + version + date, as promised, all cute and accounted for: this came to you from http://cppreference.com, dated 2024.06.10, and the page itself is std::experimental::not_fn(3). go forth and negate your callables responsibly. πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from