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

Ser*_*sen 9 c++ member-function-pointers initializer-list c++11

尝试创建int到成员函数指针的映射,并在构造函数初始值设定项中初始化它.像这样:

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;
};
Run Code Online (Sandbox Code Playgroud)

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

错误C2664'std :: map,std :: allocator >> :: map(std :: initializer_list>)':无法将参数1从'initializer list'转换为'std :: initializer_list>'

错误C2276'&':对绑定成员函数表达式的非法操作

从成员函数中删除运算符的地址时,第一条错误消息保持不变,但第二条错误消息更改为:

错误C3867'X :: setState1':非标准语法; 使用'&'创建指向成员的指针

如何在构造函数初始化列表中初始化int到成员函数指针的映射?

Sto*_*ica 14

答案通过max66是修复.至于为什么它是修复:原因是你的代码没有创建指向成员的指针.引用n4659(最后的C++ 17草案,但之前的标准版本说的相同):

[expr.unary.op/4]

仅当使用显式&时,才会形成指向成员的指针,并且其操作数是未括在括号中的qualified-id.[注意:也就是说,表达式&(qualified-id),其中qualified-id括在括号中,不形成"指向成员的指针"类型的表达式.也不是qualified-id,因为没有从非静态成员函数的qualified-id到类型"指向成员函数的指针"的隐式转换,因为从函数类型的左值到类型"指向函数的指针" ([conv.func]).即使在unqualified-id类的范围内,也不是&nonqualified-id指向成员的指针.  - 结束说明]

X::setState1是一个合格的ID,但setState1不是.


max*_*x66 9

试试吧

X() : m{ { 1, &X::setState1 } } {}
Run Code Online (Sandbox Code Playgroud)

仅使用&setState1我从g ++获取以下消息错误

错误:ISO C++禁止获取非限定或带括号的非静态成员函数的地址,以形成指向成员函数的指针.说'&X :: setState1'[-fpermissive]

从clang ++来看,错误很简单

错误:在获取其地址时必须明确限定成员函数的名称

- 编辑 -

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

要了解为什么&X::setState1有效,有效&setState1,请参阅StoryTeller的答案(+1)