与えられた
struct A {
int foo(double a, std::string& b) const;
};
次のようなメンバー関数ポインターを作成できます。
typedef int (A::*PFN_FOO)(double, std::string&) const;
PFN_FOO
の署名が変更された場合にA::foo
を更新する必要があることを除いて、十分に簡単です。 C++ 11はdecltype
を導入しているため、署名を自動的に推定してtypedefを作成するために使用できますか?
はい、もちろん:
typedef decltype(&A::foo) PFN_FOO;
using
キーワードを介してタイプエイリアスを定義することもできます(Matthieu Mに感謝):
using PFN_FOO = decltype(&A::foo);
1つの問題:この変数が明確である場合にのみ、変数の型を推定できます。
関数の主な問題はoverloadsは、それらの名前だけではそれらを特定するには不十分であることを意味します。したがって、decltype
にfoo
のオーバーロードを導入した場合、A
の使用は失敗します。
struct A {
void foo() const;
void foo(int) const;
};
using PFN_FOO = decltype(A::foo);
source.cpp:6:36: error: decltype cannot resolve address of overloaded function
このように多くを得ることができるかわからない...
一方、実際にはエイリアスを使用できますそしてエイリアスが正しいことを確認してください:
struct A {
void foo() const;
void foo(int) const;
};
using PFN_FOO = void (A::*)(int) const;
static_assert(std::is_same<PFN_FOO, decltype(static_cast<PFN_FOO>(&A::foo))>::value,
"Ooops, need to update signature of PFN_FOO!");
注:これがテストに最適な方法かどうかはわかりませんが、基本的に必要なのはstatic_cast
一部、エラーメッセージを一緒に隠しておくだけでした。より良いメッセージを得るには、おそらくSFINAEのようなものが必要でしょう。