C++11で定義される INVOKE 仮想操作の参照実装。C++1z(C++17)に向けてN4169でC++標準ライブラリ入りを提案中。
2016-07-28追記:C++1z(C++17)標準ライブラリへのstd::invoke
関数テンプレート追加が採択された。
2019-09-14追記:C++2a(C++20)標準ライブラリでは INVOKE 仮想操作をconstexpr対応するため、提案文書P1065R2が採択された。
// N4169 Implementabilityより引用 #include <functional> #include <type_traits> #include <utility> template<typename Functor, typename... Args> typename std::enable_if< std::is_member_pointer<typename std::decay<Functor>::type>::value, typename std::result_of<Functor&&(Args&&...)>::type >::type invoke(Functor&& f, Args&&... args) { return std::mem_fn(f)(std::forward<Args>(args)...); } template<typename Functor, typename... Args> typename std::enable_if< !std::is_member_pointer<typename std::decay<Functor>::type>::value, typename std::result_of<Functor&&(Args&&...)>::type >::type invoke(Functor&& f, Args&&... args) { return std::forward<Functor>(f)(std::forward<Args>(args)...); }
ファンクタfがメンバ関数/データメンバへのポインタ型の場合(20.8.2/p1/b1-4)、std::mem_fn
クラステンプレートへ処理を委譲している。C++11(N3337) 20.8.2/p1, 20.8.10/p1より一部引用。
Define
INVOKE(f, t1, t2, ..., tN)
as follows:
(t1.*f)(t2, ..., tN)
whenf
is a pointer to a member function of a classT
andt1
is an object of typeT
or a reference to an object of typeT
or a reference to an object of a type derived fromT
;((*t1).*f)(t2, ..., tN)
whenf
is a pointer to a member function of a classT
andt1
is not one of the types described in the previous item;t1.*f
whenN == 1
andf
is a pointer to member data of a classT
andt1
is an object of typeT
or a reference to an object of typeT
or a reference to an object of a type derived fromT
;(*t1).*f
whenN == 1
andf
is a pointer to member data of a classT
andt1
is not one of the types described in the previous item;f(t1, t2, ..., tN)
in all other cases.
template<class R, class T>
unspecified mem_fn(R T::* pm);
template<class R, class T, class... Args>
unspecified mem_fn(R (T::* pm)(Args...));
(snip)
Returns: A simple call wrapper (20.8.1)fn
such that the expressionfn(t, a2, ..., aN)
is equivalent toINVOKE(pm, t, a2, ..., aN)
(20.8.2). (snip)
ノート:これは単なるたらい回し実装に過ぎない。部品から組み上げる場合はlibstdc++-v3実装, libcxx実装などを参照のこと。
関連URL