Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using map's initializer list inside constructor initializer

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?

like image 549
Serve Laurijssen Avatar asked Aug 22 '17 11:08

Serve Laurijssen


People also ask

Does initializer list run before constructor?

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.

Does initializer list call constructor?

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.

When should a constructor use an initializer?

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.

What is the advantage of using member initializer 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.


1 Answers

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.

like image 81
StoryTeller - Unslander Monica Avatar answered Sep 27 '22 03:09

StoryTeller - Unslander Monica