Namespaces
Variants

std:: not_fn

From cppreference.net
Utilities library
Function objects
Function invocation
(C++17) (C++23)
Identity function object
(C++20)
Old binders and adaptors
( until C++17* )
( until C++17* )
( until C++17* )
( until C++17* )
( until C++17* ) ( until C++17* ) ( until C++17* ) ( until C++17* )
( until C++20* )
( until C++20* )
( until C++17* ) ( until C++17* )
( until C++17* ) ( until C++17* )

( until C++17* )
( until C++17* ) ( until C++17* ) ( until C++17* ) ( until C++17* )
( until C++20* )
( until C++20* )
Definido en el encabezado <functional>
template < class F >
/* no especificado */ not_fn ( F && f ) ;
(1) (desde C++17)
(constexpr desde C++20)
template < auto ConstFn >
constexpr /* no especificado */ not_fn ( ) noexcept ;
(2) (desde C++26)
1) Crea un contenedor de llamada de reenvío que devuelve la negación del objeto invocable que contiene.
2) Crea un envoltorio de llamada de reenvío que devuelve la negación del destino invocable determinado estáticamente. El programa está mal formado si ConstFn es un puntero nulo o un puntero-a-miembro nulo.

Contenidos

Parámetros

f - el objeto desde el cual se construye el objeto Callable contenido en el wrapper
Requisitos de tipo
-
std:: decay_t < F > debe cumplir con los requisitos de Callable y MoveConstructible .
-
std:: is_constructible_v < std:: decay_t < F > , F > debe ser true .

Valor de retorno

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

std::not_fn tipo de retorno

Objetos miembro

El tipo de retorno de std::not_fn contiene un objeto miembro de tipo std:: decay_t < F > .

Constructores

explicit T ( F && f ) ;
(1) (desde C++17)
(constexpr desde C++20)
( solo para exposición* )
T ( T && f ) = default ;
T ( const T & f ) = default ;
(2) (desde C++17)
1) El constructor inicializa-directamente-no-por-lista el objeto miembro (de tipo std:: decay_t < F > ) desde std:: forward < F > ( f ) . Lanza cualquier excepción lanzada por el constructor seleccionado.
2) Debido a que std:: decay_t < F > debe ser MoveConstructible , el wrapper de llamada retornado siempre es MoveConstructible , y es CopyConstructible si std:: decay_t < F > es CopyConstructible .

Las definiciones explicitamente predeterminadas hacen que el tipo de retorno no sea asignable.

(until C++20)

No está especificado si estos constructores están explicitamente predeterminados y si el tipo de retorno es asignable.

(since C++20)

Función miembro operator ( )

(1)
template < class ... Args >

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

std:: invoke_result_t < std:: decay_t < F > const & , Args... >> ( ) ) ;
(desde C++17)
(hasta C++20)
template < class ... Args >

constexpr auto operator ( ) ( Args && ... args ) &
noexcept ( /* ver más abajo */ )
- > decltype ( ! std:: invoke (
std:: declval < std:: decay_t < F > & > ( ) , std:: declval < Args > ( ) ... ) ) ;
template < class ... Args >
constexpr auto operator ( ) ( Args && ... args ) const &
noexcept ( /* ver más abajo */ )
- > decltype ( ! std:: invoke (

std:: declval < std:: decay_t < F > const & > ( ) , std:: declval < Args > ( ) ... ) ) ;
(desde C++20)
(2)
template < class ... Args >

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

std:: invoke_result_t < std:: decay_t < F > const , Args... >> ( ) ) ;
(desde C++17)
(hasta C++20)
template < class ... Args >

constexpr auto operator ( ) ( Args && ... args ) &&
noexcept ( /* ver más abajo */ )
- > decltype ( ! std:: invoke (
std:: declval < std:: decay_t < F >> ( ) , std:: declval < Args > ( ) ... ) ) ;
template < class ... Args >
constexpr auto operator ( ) ( Args && ... args ) const &&
noexcept ( /* ver más abajo */ )
- > decltype ( ! std:: invoke (

std:: declval < std:: decay_t < F > const > ( ) , std:: declval < Args > ( ) ... ) ) ;
(desde C++20)

Sea fd el objeto miembro de tipo std:: decay_t < F > .

1) Equivalente a return ! std:: invoke ( fd, std:: forward < Args > ( args ) ... ) ;
2) Equivalente a return ! std:: invoke ( std :: move ( fd ) , std:: forward < Args > ( args ) ... ) ;

Al invocar el resultado, si la sustitución en el tipo de retorno de la sobrecarga de operator ( ) originalmente seleccionada falla, puede seleccionarse otra sobrecarga .

(desde C++17)
(hasta C++20)
2) Equivalente en expresión a ! std:: invoke ( std :: move ( fd ) , std:: forward < Args > ( args ) ... )

Al invocar el resultado, si la sustitución en el tipo de retorno de la sobrecarga de operator ( ) originalmente seleccionada falla, la invocación está mal formada, lo que también puede ser un fallo de sustitución .

(desde C++20)
2) Un valor del siguiente tipo.

std::not_fn tipo de retorno sin estado

El tipo de retorno es una CopyConstructible clase sin estado. No está especificado si el tipo de retorno es asignable.

Función miembro operator ( )

template < class ... Args >

constexpr auto operator ( ) ( Args && ... args ) const
noexcept ( /* see below */ )

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

Equivalente en expresión a ! std:: invoke ( ConstFn, std:: forward < Args > ( args ) ... ) .

Excepciones

1) No lanza excepciones, a menos que la construcción de fd lance una excepción.

Implementación posible

(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::forward<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::forward<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::forward<Args>(args)...)))
        {
            return !std::invoke(std::move(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(std::move(f), std::forward<Args>(args)...)))
        {
            return !std::invoke(std::move(f), std::forward<Args>(args)...);
        }
        // Deleted overloads are needed since C++20
        // para evitar que se seleccione una sobrecarga no equivalente pero bien formada.
        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::forward<Args>(args)...)))
            -> decltype(!std::invoke(ConstFn, std::forward<Args>(args)...))
        {
            return !std::invoke(ConstFn, std::forward<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 {};
}

Notas

std::not_fn está destinado a reemplazar los negadores de la era C++03 std::not1 y std::not2 .

Macro de prueba de características Valor Std Característica
__cpp_lib_not_fn 201603L (C++17) std::not_fn() , ( 1 )
202306L (C++26) Permitir pasar objetos invocables como argumentos de plantilla constantes a std::not_fn , ( 2 )

Ejemplo

#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()
{
    // Uso con una función libre:
    auto is_differ = std::not_fn(is_same);
    assert(is_differ(8, 8) == false); // equivalente a: !is_same(8, 8) == false
    assert(is_differ(6, 9) == true); // equivalente a: !is_same(8, 0) == true
    // Uso con una función miembro:
    auto member_differ = std::not_fn(&S::is_same);
    assert(member_differ(S{3}, 3) == false); //: S tmp{6}; !tmp.is_same(6) == false
    // La especificación noexcept se preserva:
    static_assert(noexcept(is_differ) == noexcept(is_same));
    static_assert(noexcept(member_differ) == noexcept(&S::is_same));
    // Uso con un objeto función:
    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
}

Véase también

(deprecated in C++17) (removed in C++20)
construye un objeto personalizado std::unary_negate
(plantilla de función)
(deprecated in C++17) (removed in C++20)
construye un objeto personalizado std::binary_negate
(plantilla de función)