在构造函数初始化程序中使用map的初始化程序列表

问题描述:

尝试创建int成员函数指针映射并在构造函数初始化程序中初始化它。 像这样:在构造函数初始化程序中使用map的初始化程序列表

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; 
}; 

我会说这是正确的,但Visual Studio的2017年说:

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

'identifier' can永远不要使用成员函数的地址(明确用'&'或衰减);你总是必须使用合格的身份证号码 –

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

只使用&setState1我得到的,从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]

从铛++错误尝试仅仅是

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

- 编辑 -

我的答案解释了如何解决问题。

要理解为什么&X::setState1作品和&setState1没有,请参阅说书人的答案(+1)

answer通过max66是修复。至于为什么这是修复:原因是你的代码不会创建一个指向成员的指针。引述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

我想这是有很好的理由。例如。人们会认为'&m''是类型'std :: map *''的类型,所以需要一个不同的语法,特别是'&X :: m''来获得一个'std: :map X :: *''。然后要求后者的语法也适用于非静态方法,即使使用unqualified-id的语法是非法的。 –

+0

@ArneVogel - 你非常正确。此外,在定义指向成员的指针时,甚至不需要在成员函数和数据成员之间进行区分。如果我们有'TC :: * pm = &C::m;',那么无论'T'是一个对象类型(哪一个匹配)或者一个函数别名如'using T = void(void);'这个原型的成员函数)。尽管冗长,但这种方式的语法非常一致。 – StoryTeller