Trying to create a map of int to member function pointer and initialize it inside a constructor initializer. Like this:
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;
};
I would say this is correct, but Visual studio 2017 says:
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
When you remove the address of operator from the member function the first error message stays the same but the second changes to:
Error C3867 'X::setState1': non-standard syntax; use '&' to create a pointer to member
How do you initialize a map of int to member function pointer inside a constructor initializer list?
As already answered, initialization lists get completely executed before entering the constructor block. So it is completely safe to use (initialized) members in the constructor body.
An initialization list can be used to explicitly call a constructor that takes arguments for a data member that is an object of another class (see the employee constructor example above). In a derived class constructor, an initialization list can be used to explicitly call a base class constructor that takes arguments.
Initialization lists allow you to choose which constructor is called and what arguments that constructor receives. If you have a reference or a const field, or if one of the classes used does not have a default constructor, you must use an initialization list.
The most common benefit of doing this is improved performance. If the expression whatever is the same type as member variable x_, the result of the whatever expression is constructed directly inside x_ — the compiler does not make a separate copy of the object.
The answer by max66 is the fix. As for why it's the fix: the reason is that your code does not create a pointer to a member. To quote n4659 (last C++17 draft, but previous standard revisions say the same):
[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
is a qualified id, but setState1
is not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With