最終更新日時: 2025年07月10日 10時26分30秒 (JST)
Koichi Murase が更新

履歴 編集

function template
<functional>

# std::invoke(C++17)

    namespace std {
      template <class F, class... Args>
      invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
        noexcept(is_nothrow_invocable_v<F, Args...>);           //C++17

      template <class F, class... Args>
      constexpr invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
        noexcept(is_nothrow_invocable_v<F, Args...>);           //C++20
    }

## 概要

関数呼び出し可能なオブジェクト`f`とその引数`args...`の組み合わせでINVOKE要件に従った関数呼び出しを行う。

INVOKE要件とはC++における関数呼び出しという性質を抽象化しまとめた概念であり、`invoke`はその実体化、すなわち関数呼び出しという操作を統一したものである。

## 要件

型`F`および`Args...`の組み合わせでINVOKE要件に従った関数呼び出しが可能であり、オーバーロード解決の結果が曖昧にならないこと。そうでない場合はコンパイルエラーとなる。

## 引数

- `f` -- Callable オブジェクト（関数ポインタ/参照・関数オブジェクト・メンバポインタ）
- `args...` -- `f`に与える引数列。`f`がメンバポインタである場合は対応するクラスのオブジェクト（もしくはそのreference_wrapper）が`args...`の先頭になければならない

## 戻り値

`f`と`args...`によりINVOKE要件に従った関数呼び出しを行い、その結果を戻り値として返す。

## 例外

`f`の`args...`による関数呼び出しに際して例外を投げない（`is_nothrow_invocable_v<F, Args...> == true`）ならば、この関数も例外を投げない。

## 例

    #include <iostream>
    #include <functional>

    struct functor {
      auto operator()() -> int {
        return 10;
      }

      auto operator()(int n) -> int {
        return n;
      }
    };

    struct has_member {
      auto member_function(int n) -> int {
        return n;
      }

      int member_object;
    };

    auto f(int) -> double {
      return 3.14159265359;
    }

    auto g(int) -> double {
      return 2.71828182846;
    }

    auto g(int,int) -> double {
      return 3.14159265359;
    }

    int main()
    {
      functor fobj{};

      //関数オブジェクト呼び出し
      std::cout << std::invoke(fobj) << std::endl;
      std::cout << std::invoke(fobj, 100) << std::endl;

      has_member obj{25};
      //メンバ関数呼び出し
      std::cout << std::invoke(&has_member::member_function, obj, 50) << std::endl;
      //メンバ変数呼び出し
      std::cout << std::invoke(&has_member::member_object, obj) << std::endl;

      auto ref = std::ref(obj);
      //reference_wrapperからのメンバ関数呼び出し
      std::cout << std::invoke(&has_member::member_function, ref, 50) << std::endl;
      //reference_wrapperからのメンバ変数呼び出し
      std::cout << std::invoke(&has_member::member_object, ref) << std::endl;

      //関数呼び出し
      std::cout << std::invoke(f, 10) << std::endl;

      //フリー関数は一度関数ポインタにしないとオーバーロード解決できない
      std::cout << std::invoke((double(*)(int))g, 10) << std::endl;
      std::cout << std::invoke((double(*)(int, int))g, 10, 10) << std::endl;

      //コンパイルエラー
      //std::cout << std::invoke(g, 10) << std::endl;
    }

### 出力

    10
    100
    50
    25
    50
    25
    3.14159
    2.71828
    3.14159

## バージョン

### 言語

- C++17

### 処理系

- Clang: ??
- GCC: ??
- Visual C++: 2015 ✅, 2017 ✅

## 関連項目

- `invoke_r`
- `invoke_result`
- `is_invocable`
- `is_nothrow_invocable`

## 参照

- C++1z INVOKEコンセプトに従った関数呼び出しをするinvoke()関数 - Faith and Brave - C++で遊ぼう
- N4169 A proposal to add invoke function template (Revision 1)
- P1065R2 constexpr INVOKE