2017-08-22 27 views
9

メンバ関数ポインタへのintのマップを作成し、コンストラクタの初期化子の内部で初期化しようとしています。このよう :私は、これは正しいが、Visual Studioの2017年であると言うでしょうコンストラクタの初期化子内のマップの初期化子リストを使用

class X 
{ 
    using STATEFUNC = void(X::*)(int); 
public: 
    X() : m{ { 1, &setState1 } } {} 

    void setState1(int x) { cout << "state1" << endl; } 

    void setState2(int x) { cout << "state2" << endl; } 


    std::map<int, STATEFUNC> m; 
}; 

は言う:

Error C2664 'std::map,std::allocator>>::map(std::initializer_list>)': cannot convert argument 1 from 'initializer list' to 'std::initializer_list>'

Error C2276 '&': illegal operation on bound member function expression

を使用すると、メンバ関数からオペレータのアドレスを削除すると、最初のエラーメッセージは同じままが、

Error C3867 'X::setState1': non-standard syntax; use '&' to create a pointer to member

intのマップをコンストラクタの初期化子リストの中でメンバ関数ポインタに初期化するにはどうすればよいですか?

+3

興味深い。理由は分かりませんが、クラス名が必要です。なぜなら、X():m {{1、&X :: setState1}} {} 'は動作するが、' X():m {{1、&setState1}} {} 'は – NathanOliver

+1

'メンバー関数のアドレスを明示的に( '&'または崩壊によって)取ることは決してできません。あなたは常に修飾IDを使用しなければなりません –

答えて

9

エラーは単に

error: must explicitly qualify name of member function when taking its address

です++打ち鳴らすから

のみ&setState1 IがG ++から、取得するには、次のメッセージエラー

error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say ‘&X::setState1’ [-fpermissive]

を使用して

X() : m{ { 1, &X::setState1 } } {} 

で試してみてください - EDIT -

私の答えは、問題の解決方法を説明しています。

&X::setState1作品や&setState1は、落語の回答を参照してくださいしない理由を理解するには(1)

14

answermax66によって修正です。それがなぜ修正されたのかについては、あなたのコードがメンバへのポインタを作成しないという理由があります。 n4659を引用(最後のC++ 17ドラフトが、以前の標準のリビジョンが同じことを言う)するには:

[expr.unary.op/4]

A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses. [ Note: That is, the expression &(qualified-id), where the qualified-id is enclosed in parentheses, does not form an expression of type “pointer to member”. Neither does qualified-id, because there is no implicit conversion from a qualified-id for a non-static member function to the type “pointer to member function” as there is from an lvalue of function type to the type “pointer to function” ([conv.func]). Nor is &unqualified-id a pointer to member, even within the scope of the unqualified-id's class.  — end note ]

X::setState1は、資格のIDですが、setState1ではありません。

+0

この区別には正当な理由があると私は思います。例えば。 '' std :: map * ''型であることが期待されるので、異なる構文が必要です。具体的には ''&X :: m''が '' std: :map X :: * ''。 unqualified-idを持つ構文が不正であっても、非静的メソッドに対しても後者の構文を要求することは一貫しています。 –

+0

@ArneVogel - あなたは非常に正しいです。さらに、メンバへのポインタを定義するときに、メンバ関数とデータメンバを区別する必要さえありません。 'TC :: * pm = &C::m;'の場合、宣言は、 'T'がオブジェクト型(mがマッチする)であるか' using T = void(void); '(' m is isこのプロトタイプを持つメンバ関数)。構文は、冗長にもかかわらず、このように*非常に一貫性があります。 – StoryTeller

関連する問題