最終更新日時(UTC):
が更新

履歴 編集

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...の先頭になければならない

戻り値

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

例外

fargs...による関数呼び出しに際して例外を投げない(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

処理系

関連項目

参照