Namespaces
Variants

std::not_fn

С сайта ru.cppreference.net
 
 
Библиотека утилит
Поддержка языка
Поддержка типов (базовые типы, RTTI)
Макросы проверки возможностей библиотеки (C++20)
Программные утилиты
Функции с переменным числом аргументов
Поддержка корутин (C++20)
Поддержка контрактов (C++26)
Трёхстороннее сравнение
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Общие утилиты
Операторы отношений (устарело в C++20)
 
Функциональные объекты
Вызов функции
(C++17)(C++23)
Функциональный объект тождественности
(C++20)
Старые связыватели и адапторы
(до C++17*)
(до C++17*)
(до C++17*)
(до C++17*)
(до C++17*)(до C++17*)(до C++17*)(до C++17*)
(до C++20*)
(до C++20*)
(до C++17*)(до C++17*)
(до C++17*)(до C++17*)

(до C++17*)
(до C++17*)(до C++17*)(до C++17*)(до C++17*)
(до C++20*)
(до C++20*)
 
Определён в заголовке <functional>
template< class F >
/* unspecified */ not_fn( F&& f );
(1) (начиная с C++17)
(constexpr начиная с C++20)
template< auto ConstFn >
constexpr /* unspecified */ not_fn() noexcept;
(2) (начиная с C++26)
1) Создаёт прямую обёртку вызова, возвращающую отрицание хранимого вызываемого объекта.
2) Создаёт прямую обёртку вызова, возвращающую отрицание статически определённой вызываемой цели. Программа считается некорректной, если ConstFn является нулевым указателем или нулевым указателем на член.

Параметры

f - объект, из которого конструируется Callable объект, хранящийся в обёртке
Требования к типам
-
std:: decay_t < F > должен удовлетворять требованиям Callable и MoveConstructible .
-
std:: is_constructible_v < std:: decay_t < F > , F > должно быть true .

Возвращаемое значение

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

std::not_fn тип возвращаемого значения

Объекты-члены

Возвращаемый тип std::not_fn содержит объект-член типа std:: decay_t < F > .

Конструкторы

explicit T ( F && f ) ;
(1) (начиная с C++17)
(constexpr начиная с C++20)
( только для демонстрации* )
T ( T && f ) = default ;
T ( const T & f ) = default ;
(2) (начиная с C++17)
1) Конструктор выполняет прямую несписочную инициализацию объекта-члена (типа std:: decay_t < F > ) из std:: forward < F > ( f ) . Выбрасывает любое исключение, выброшенное выбранным конструктором.
2) Поскольку std:: decay_t < F > должен быть MoveConstructible , возвращаемая обёртка вызова всегда является MoveConstructible и является CopyConstructible , если std:: decay_t < F > является CopyConstructible .

Явно определенные по умолчанию определения делают возвращаемый тип не присваиваемым.

(until C++20)

Не определено, являются ли эти конструкторы явно определенными по умолчанию и является ли возвращаемый тип присваиваемым.

(since C++20)

Функция-член 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... >> ( ) ) ;
(начиная с C++17)
(до C++20)
template < class ... Args >

constexpr auto operator ( ) ( Args && ... args ) &
noexcept ( /* см. ниже */ )
- > decltype ( ! std:: invoke (
std:: declval < std:: decay_t < F > & > ( ) , std:: declval < Args > ( ) ... ) ) ;
template < class ... Args >
constexpr auto operator ( ) ( Args && ... args ) const &
noexcept ( /* см. ниже */ )
- > decltype ( ! std:: invoke (

std:: declval < std:: decay_t < F > const & > ( ) , std:: declval < Args > ( ) ... ) ) ;
(начиная с 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... >> ( ) ) ;
(начиная с C++17)
(до C++20)
template < class ... Args >

constexpr auto operator ( ) ( Args && ... args ) &&
noexcept ( /* см. ниже */ )
- > decltype ( ! std:: invoke (
std:: declval < std:: decay_t < F >> ( ) , std:: declval < Args > ( ) ... ) ) ;
template < class ... Args >
constexpr auto operator ( ) ( Args && ... args ) const &&
noexcept ( /* см. ниже */ )
- > decltype ( ! std:: invoke (

std:: declval < std:: decay_t < F > const > ( ) , std:: declval < Args > ( ) ... ) ) ;
(начиная с C++20)

Пусть fd будет объектом-членом типа std:: decay_t < F > .

1) Эквивалентно return ! std:: invoke ( fd, std:: forward < Args > ( args ) ... ) ;
2) Эквивалентно return ! std:: invoke ( std :: move ( fd ) , std:: forward < Args > ( args ) ... ) ;

При вызове результата, если подстановка в возвращаемый тип изначально выбранной operator ( ) перегрузки завершается неудачей, может быть выбрана другая перегрузка .

(начиная с C++17)
(до C++20)

При вызове результата, если подстановка в возвращаемый тип изначально выбранной operator ( ) перегрузки завершается неудачей, вызов является некорректным, что также может быть ошибкой подстановки .

(начиная с C++20)
2) Значение следующего типа.

std::not_fn stateless return type

Возвращаемый тип представляет собой CopyConstructible статический класс без состояния. Не указано, является ли возвращаемый тип присваиваемым.

Функция-член operator ( )

template < class ... Args >

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

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

Эквивалентно выражению ! std:: invoke ( ConstFn, std:: forward < Args > ( args ) ... ) .

Исключения

1) Не вызывает исключений, если только конструкция fd не вызывает исключение.

Возможная реализация

**Примечание:** Весь код C++ внутри тегов `
` и `` оставлен без изменений, как и требовалось. HTML-теги и атрибуты также сохранены в оригинальном виде.
(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)...);
        }
        // Удаленные перегрузки необходимы начиная с C++20
        // для предотвращения выбора неэквивалентной, но корректно сформированной перегрузки.
        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 {};
}

Примечания

std::not_fn предназначен для замены негаторов эпохи C++03 std::not1 и std::not2 .

Макрос тестирования возможностей Значение Стандарт Функция
__cpp_lib_not_fn 201603L (C++17) std::not_fn() , ( 1 )
202306L (C++26) Разрешение передачи вызываемых объектов как константных шаблонных аргументов в std::not_fn , ( 2 )

Пример

#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()
{
    // Использование со свободной функцией:
    auto is_differ = std::not_fn(is_same);
    assert(is_differ(8, 8) == false); // эквивалентно: !is_same(8, 8) == false
    assert(is_differ(6, 9) == true); // эквивалентно: !is_same(8, 0) == true
    // Использование с функцией-членом:
    auto member_differ = std::not_fn(&S::is_same);
    assert(member_differ(S{3}, 3) == false); //: S tmp{6}; !tmp.is_same(6) == false
    // Спецификация noexcept сохраняется:
    static_assert(noexcept(is_differ) == noexcept(is_same));
    static_assert(noexcept(member_differ) == noexcept(&S::is_same));
    // Использование с функциональным объектом:
    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
}

Смотрите также

(deprecated in C++17) (removed in C++20)
создает пользовательский объект std::unary_negate
(шаблон функции)
(deprecated in C++17) (removed in C++20)
создает пользовательский объект std::binary_negate
(шаблон функции)