web-dev-qa-db-ja.com

C ++ 11 decltypeを使用して、既存の関数から関数ポインターのtypedefを作成できますか?

与えられた

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を作成するために使用できますか?

31
Daniel Gehriger

はい、もちろん:

typedef decltype(&A::foo) PFN_FOO;

using キーワードを介してタイプエイリアスを定義することもできます(Matthieu Mに感謝):

using PFN_FOO = decltype(&A::foo);

45
Rost

1つの問題:この変数が明確である場合にのみ、変数の型を推定できます。

関数の主な問題はoverloadsは、それらの名前だけではそれらを特定するには不十分であることを意味します。したがって、decltypefooのオーバーロードを導入した場合、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のようなものが必要でしょう。

19
Matthieu M.