【问题标题】:using map's initializer list inside constructor initializer在构造函数初始化程序中使用地图的初始化程序列表
【发布时间】:2018-01-30 16:32:45
【问题描述】:

尝试创建一个 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;
};

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

错误 C2664 'std::map,std::allocator>>::map(std::initializer_list>)': 无法将参数 1 从“初始化列表”转换为 'std::initializer_list>'

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

当您从成员函数中删除操作员的地址时,第一个错误消息保持不变,但第二个更改为:

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

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

【问题讨论】:

  • 有趣。不知道为什么,但它需要这里的类名。希望有人会知道为什么X() : m{ { 1, &amp;X::setState1 } } {} 有效但X() : m{ { 1, &amp;setState1 } } {} 无效
  • identifier 永远不能用于获取成员函数的地址(显式使用 &amp; 或通过衰减);你总是必须使用一个合格的ID

标签: c++ c++11 initializer-list member-function-pointers


【解决方案1】:

试试

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

仅使用 &amp;setState1 我从 g++ 得到以下消息错误

错误:ISO C++ 禁止使用不合格或带括号的非静态成员函数的地址来形成指向成员函数的指针。说'&X::setState1' [-fpermissive]

从 clang++ 错误只是

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

-- 编辑--

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

要了解为什么 &amp;X::setState1 有效而 &amp;setState1 无效,请参阅 StoryTeller 的回答 (+1)

【讨论】:

    【解决方案2】:

    max66answer 是解决方法。至于为什么要修复:原因是您的代码没有创建指向成员的指针。引用 n4659(最新的 C++17 草案,但以前的标准修订版也一样):

    [expr.unary.op/4]

    只有在使用显式 & 并且它的 操作数是没有括在括号中的限定 ID。 [ 注意: 是表达式 &(qualified-id),其中包含了qualified-id 在括号中,不形成类型为“pointer to 成员”。 qualified-id 也没有,因为没有隐式 从非静态成员函数的限定 ID 转换为 键入“指向成员函数的指针”,因为它来自左值 函数类型到类型“函数指针”([conv.func])。 也不是 &unqualified-id 指向成员的指针,即使在 unqualified-id 的类。  — 尾注 ]

    X::setState1 是一个合格的 id,但 setState1 不是。

    【讨论】:

    • 我认为这种区别是有充分理由的。例如。人们会期望&amp;m 的类型为std::map&lt;int, STATEFUNC&gt; *,因此需要不同的语法,特别是&amp;X::m 来获得std::map&lt;int, STATEFUNC&gt; X::*。然后,对于非静态方法也要求后一种语法是一致的,即使带有 unqualified-id 的语法是非法的。
    • @ArneVogel - 你非常正确。此外,在定义指向成员的指针时,甚至不需要区分成员函数和数据成员。如果我们有T C::* pm = &amp;C::m;,那么无论T 是对象类型(m 匹配)还是像using T = void(void); 这样的函数别名(m 是具有此原型的成员函数),声明都是正确的。尽管冗长,但语法非常一致
    猜你喜欢
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多