在构造函数初始化程序中使用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映射初始化为构造函数初始值设定项列表中的成员函数指针?
与
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草案,但以前的标准版本说的一样):
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
不是。
我想这是有很好的理由。例如。人们会认为'&m''是类型'std :: map
@ArneVogel - 你非常正确。此外,在定义指向成员的指针时,甚至不需要在成员函数和数据成员之间进行区分。如果我们有'TC :: * pm = &C::m;',那么无论'T'是一个对象类型(哪一个匹配)或者一个函数别名如'using T = void(void);'这个原型的成员函数)。尽管冗长,但这种方式的语法非常一致。 – StoryTeller
有趣。不知道为什么,但它需要在这里的类名称。希望有人会知道为什么'X():m {{1,&X :: setState1}} {}'工作,但是'X():m {{1,&setState1}} {}'不' – NathanOliver
'identifier' can永远不要使用成员函数的地址(明确用'&'或衰减);你总是必须使用合格的身份证号码 –