最終更新日時: 2025年08月31日 21時36分04秒 (JST)
Raclamusi が更新

履歴 編集

function template
<functional>

# std::not_fn(C++17)

    namespace std {
      template <class F>
      unspecified not_fn(F&& f);            // (1) C++17
      template <class F>
      constexpr unspecified not_fn(F&& f);  // (1) C++20

      template <auto f>
      constexpr unspecified not_fn();  // (2) C++26
    }

## 概要

任意個数の引数をとって`bool`型を返す関数オブジェクトを受け取り、戻り値を論理反転する関数オブジェクトに変換する。

## 事前条件

- (1) : `decay_t<F>`を適用した型を`FD`として、`FD`がCpp17MoveConstructible要件を満たすこと

## 適格要件

- (1) : `decay_t<F>`を適用した型を`FD`として、
  - `is_constructible_v<FD, F>`が`true`、かつ
  - `is_move_constructible_v<FD>`が`true`であること
- (2) : `F`を`f`の型として、もし`is_pointer_v<F> || is_member_pointer_v<F>`が`true`ならば、`f != nullptr`であること

## 効果(C++17)

説明用の関数オブジェクト`call_wrapper`があるものとして、`call_wrapper(std::forward<F>(f))`を返す。

説明用の関数オブジェクト`call_wrapper`は、以下のようなクラスである：

    class call_wrapper {
      using FD = decay_t<F>;

      explicit call_wrapper(F&& f); // not_fnをfriendにして呼び出す

    public:
      call_wrapper(call_wrapper&&) = default;
      call_wrapper(call_wrapper const&) = default;

      template <class... Args>
      auto operator()(Args&&...) & -> decltype(!declval<invoke_result_t<FD&, Args&&...>>());

      template <class... Args>
      auto operator()(Args&&...) const& -> decltype(!declval<invoke_result_t<FD const&, Args&&...>>());

      template <class... Args>
      auto operator()(Args&&...) && -> decltype(!declval<invoke_result_t<FD, Args&&...>>());

      template <class... Args>
      auto operator()(Args&&...) const&& -> decltype(!declval<invoke_result_t<FD const, Args&&...>>());

    private:
      FD fd;
    };

このクラスのコンストラクタは、式`fd = std::forward<F>(f)`を実行する。この式が例外を送出する可能性がある。

このクラスの関数オブジェクトは、以下の式を実行する：

- 左辺値参照版 : `return !INVOKE(fd, std::forward<Args>(args)...)`
- 右辺値参照版 : `return !INVOKE(std::move(fd), std::forward<Args>(args)...)`

## 戻り値(C++20)

結果オブジェクト`g`に対する関数呼び出し式の引数パック`call_args`としたとき

- (1) : `fd`を`std::forward<F>(f)`で直接非リスト初期化した`FD`型のオブジェクトに対して
  - 関数呼び出し式の結果が`!invoke(fd, call_args...)`に等しい、完全転送呼び出しラッパー(perfect forwarding call wrapper)オブジェクトを返す。
- (2) :
  - 関数呼び出し式の結果が`!invoke(f, call_args...)`に等しい、状態を持たない完全転送呼び出しラッパー(perfect forwarding call wrapper)オブジェクトを返す。

## 例外

- (1) : 関数オブジェクト`f`のムーブによって任意の例外が送出される可能性がある

## 例

    #include <iostream>
    #include <functional>

    bool pred_func(int, char, double)
    {
      return true;
    }

    struct pred_functor {
      bool operator()(double, int)
      {
        return false;
      }
    };

    int main()
    {
      std::cout << std::boolalpha;

      auto not_func = std::not_fn(pred_func);
      std::cout << not_func(1, 'a', 3.14) << std::endl;

      auto not_functor = std::not_fn(pred_functor{});
      std::cout << not_functor(3.14, 1) << std::endl;
    }

### 出力

    false
    true

## バージョン

### 言語

- C++17

### 処理系

- Clang: 3.9.1 ✅
- GCC: 7.2 ✅
- ICC: ??
- Visual C++: ??

## 参照

- P0005R4 Adopt `not_fn` from Library Fundamentals 2 for C++17
- LWG Issue 2767. `not_fn call_wrapper` can form invalid types
- P0356R5 Simplified partial function application
- P1065R2 constexpr INVOKE
- P2714R1 Bind front and back to NTTP callables
  - C++26でオーバーロード(2)を追加