Matteo
Matteo

Reputation: 171

vector of function pointers

I'm trying to code a Gameboy emulator and i would like to use a vector of function pointers to call the right function instead of doing a long switch statement.

For example if the program counter point to 0x00 (in memory), the first element of the vector is NOP so void NOP() is called; but i can't figure how to call the functions.

Z80.h

#include <vector>
using namespace std;

class Z80;
typedef void (Z80::*function_t)();

class Z80
{
public:
  vector<function_t> fmap;
...
...
};

Z80.cpp

Z80::Z80()
{
    fmap = { &Z80::NOP, &Z80::LDBCnn, &Z80::LDBCmA};
}

void Z80::emulateCycle() {
    opcode = memory.readByte(r.pc);
    fmap[opcode]();     <---ERROR
    r.pc++;
}

void Z80::NOP() {

}

this is the error:

IntelliSense: expression preceding parentheses of apparent call must have (pointer-to-) function type

Upvotes: 4

Views: 2344

Answers (2)

Mats Petersson
Mats Petersson

Reputation: 129374

I'm not entirely sure that using function pointer in this case is particularly much better than for example a big switch statement.

However, the reason you can't call your member function is that you are not passing your object to the function.

You need this;

(this->*fmap[opcode])();

Another option is to use static/free function pointers, like this:

 void (*function_t)(Z80& self); 

and call it with:

 fmap[opcode](this). 

[Or use std::function and std::bind, which covers over the rather (intentionally, apparently) ugly syntax]

Upvotes: 5

Barry
Barry

Reputation: 303186

This expression:

fmap[opcode]

gives you a pointer to a member function. You can't just call that - it needs the class instance too. But you're actually calling it from a class method itself - so this is the instance you're looking for:

(this->*fmap[opcode])();

Note that if you want to avoid that bit of syntax and you're using C++11, you can change your fmap to instead be a vector of std::function<void()> and initialize it thusly:

fmap = { std::bind(&Z80::NOP, this),    // or [this](){ this->NOP(); }
         std::bind(&Z80::LDBCnn, this), // etc.
         std::bind(&Z80::LDBCmA, this)};

That will let you actually do:

fmap[opcode]();

Upvotes: 5

Related Questions