Vega4
Vega4

Reputation: 979

typedef + pointer to a member function

I get an error when initializing a typedef-ed pointer to a member function. Is it because it is typedef-ed before classs declaration? If so, how can I forward declare the typedef so it can be used inside of struct Definition which is then used inside of the B class itself.

Header file:

typedef void (B::* p)()

struct Definition {
   p code = nullptr;
    void execute() {
        code();
    }
}

class B
{

private:
    void semicolon();
    p o;
    void (B::* pointer)();
    std::list<Definition> definitions;
    void definePrimitives();
}

Source file:

void B::definePrimitives() {    
    o= B::semicolon;// error: expression must be a modifiable l-value   
    pointer =&B::semicolon;//works
}

Upvotes: 1

Views: 1212

Answers (2)

Vega4
Vega4

Reputation: 979

The code had a couple of problems: 1) it lacked forward declaration of class B as pointed out by IlBeldus. If you remove forward declaration of class B you will be able to reproduce the error. 2) the execute method inside of Definition struct was wrong. It should be:

  struct Definition {
    Code   code = nullptr;
    void execute(B b) {
        b.o = &B::semicolon;
        (b.*(b.c))();
    }
};

in my real application I've defined pointer to B to as a member of Definition. One can't just execute member function by

p(); or code();

one needs to specify the object of type B first, like in my example above:

(b.*(b.c))();

3) Thirdly, my code required struct Definition to be declared below B, and struct Definition had to be forward-declared before B. just like this:

header file:

 #include <list>
class B;
using Code = void(B::*)(void);

struct Definition;

class B
{

private:

    void (B::* pointer)();
std::list<Definition> definitions;
    void definePrimitives();
public:
    void semicolon();
    Code o = nullptr;
    Code c = nullptr;
};

struct Definition {
    Code   code = nullptr;
    void execute(B b) {
        b.o = &B::semicolon;
        (b.*(b.c))();
    }
};

and source file:

 #include "Header.h"
    #include <list>

    void B::semicolon()
    {
    }

    void B::definePrimitives() {
        o = &B::semicolon;
        pointer = &B::semicolon;
    }

    int main() {
        B b;
        return 0;
    }

4) and.. in the C++ world one my want to use classes instead of structs all the way, and since we are past c++11 already one might want to use the using clause, instead of typedef.

Upvotes: 0

IlBeldus
IlBeldus

Reputation: 1040

This works:

class B;
typedef void (B::* p)();

struct Definition {
    void execute() {
        p();
    }
};

class B
{

private:
    void semicolon();
    p o;
    void (B::* pointer)();
    std::list<Definition> definitions;
    void definePrimitives() {
        o= &B::semicolon;
        pointer =&B::semicolon;
    }
};

Basically you have to take the pointer to the function, not the function itself

Upvotes: 1

Related Questions