C++11標準ライブラリのstd::functionやstd::bindでは、クラスのデータメンバ(メンバ変数)を格納できる。
#include <functional> struct A { int md; void mf(int v) { md = v * 2; } } a; // メンバ関数 A::mf (比較用) std::function<void (A&, int)> f1 = &A::mf; f1(a, 3); // a.mf(3) assert(a.md == 6); using std::placeholers::_1; std::function<void (int)> b1 = std::bind(&A::mf, std::ref(a), _1); b1(4); // a.mf(4) assert(a.md == 8); // データメンバ A::md std::function<int& (A&)> f2 = &A::md; f2(a) = 42; // a.md = 42 assert(a.md == 42); std::function<int& ()> b2 = std::bind(&A::md, std::ref(a)); b2() /= 2; // a.md /= 2 assert(a.md == 21);
Boostライブラリのfunctionとbindも同等機能を有する(Boost 1.49.0で動作確認)。ただしboost::bindの第一引数ではboost::function<int&(A&)>への明示的なキャストが必要。ここまでして使う意義があるかは疑問...
#include <boost/function.hpp> a.md = 21; boost::function<int& (A&)> f2 = &A::md; f2(a) *= 2; assert(a.md == 42); // NG: boost::function<int& ()> b2 = boost::bind(&A::md, boost::ref(a)) boost::function<int& ()> b2 = boost::bind( boost::function<int& (A&)>(&A::md), boost::ref(a) ); b2() -= 10; assert(a.md == 32);
2012-03-08追記:boost::bindの戻り値型R=int&を明示指定すれば良かった。(thanks to [twitter:@manga_osyo]さん)
boost::function<int& ()> b2 = boost::bind<int&>(&A::md, boost::ref(a));
N3337 20.8.2/p1, 20.8.11.2.4/p1-2より引用。(下線部は強調)
1 Define
INVOKE(f, t1, t2, ..., tN)as follows:
(t1.*f)(t2, ..., tN)whenfis a pointer to a member function of a classTandt1is an object of typeTor a reference to an object of typeTor a reference to an object of a type derived fromT;((*t1).*f)(t2, ..., tN)whenfis a pointer to a member function of a classTandt1is not one of the types described in the previous item;t1.*fwhenN == 1andfis a pointer to member data of a classTandt1is an object of typeTor a reference to an object of typeTor a reference to an object of a type derived fromT;(*t1).*fwhenN == 1andfis a pointer to member data of a classTandt1is not one of the types described in the previous item;f(t1, t2, ..., tN)in all other cases.
R operator()(ArgTypes... args) const
1 Effects:INVOKE(f, std::forward<ArgTypes>(args)..., R)(20.8.2), wherefis the target object (20.8.1) of*this.
2 Returns: Nothing ifRisvoid, otherwise the return value ofINVOKE(f, std::forward<ArgTypes>(args)..., R).
関連URL