Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 737
Matteo Avatar asked Dec 25 '22 23:12

Matteo


2 Answers

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]();
like image 159
Barry Avatar answered Jan 03 '23 00:01

Barry


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]

like image 39
Mats Petersson Avatar answered Jan 02 '23 23:01

Mats Petersson