>The function pointer syntax is painful and there are some quirks in
>the grammar as a result. It's been my experience that as soon as you
>need one callback, you need a second one in short order.
I've used them, on occasion. One becomes accustomed to the syntax.
if (branch || !p_fetch_fault) {
failed = (this->*opp->op_insn)(opp);
}
This was in an instruction decoder dispatch loop.
struct p_op {
const char *op_name; // Opcode name
unsigned char op_opcode; // 2-digit numeric opcode
unsigned char op_operands; // Operand count
unsigned char op_literal:1, // A field literal allowed
op_afindirect:1, // AF indirect allowed
op_bfindirect:1, // BF indirect allowed
op_flags:1, // COM/OVF flags modified
op_bfhex:1, // Treat BF field as hex
op_noafbf:1; // No AFBF field for instruction
bool (c_processor::*op_insn)(struct _op *);
};
struct c_processor::p_op c_processor::p_optable[] = {
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 1, &c_processor::op_nul }, // 00
{ "INC", OP_INC, 2, 1, 1, 1, 1, 0, 0, &c_processor::op_inc }, // 01
{ "ADD", OP_ADD, 3, 1, 1, 1, 1, 0, 0, &c_processor::op_add }, // 02
{ "DEC", OP_DEC, 2, 1, 1, 1, 1, 0, 0, &c_processor::op_dec }, // 03
{ "SUB", OP_SUB, 3, 1, 1, 1, 1, 0, 0, &c_processor::op_sub }, // 04
{ "MPY", OP_MPY, 3, 1, 1, 1, 1, 0, 0, &c_processor::op_mpy }, // 05
{ "DIV", OP_DIV, 3, 1, 1, 1, 1, 0, 0, &c_processor::op_div }, // 06
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 0, &c_processor::op_nul }, // 07
{ "MVD", OP_MVD, 3, 0, 1, 1, 0, 0, 0, &c_processor::op_mvd }, // 08
{ "MVL", OP_MVL, 3, 0, 1, 1, 0, 0, 0, &c_processor::op_mvl }, // 09
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 1, &c_processor::op_nul }, // 0a
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 1, &c_processor::op_nul }, // 0b
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 1, &c_processor::op_nul }, // 0c
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 1, &c_processor::op_nul }, // 0d
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 1, &c_processor::op_nul }, // 0e
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 1, &c_processor::op_nul }, // 0f
{ "MVA", OP_MVA, 2, 1, 1, 1, 1, 0, 0, &c_processor::op_mva }, // 10
{ "MVN", OP_MVN, 2, 1, 1, 1, 1, 0, 0, &c_processor::op_mvn }, // 11
{ "MVW", OP_MVW, 2, 0, 1, 1, 0, 0, 0, &c_processor::op_mvw }, // 12
{ "MVC", OP_MVC, 2, 0, 1, 1, 0, 0, 0, &c_processor::op_mvc }, // 13
{ "MVR", OP_MVR, 2, 1, 1, 1, 0, 0, 0, &c_processor::op_mvr }, // 14
{ "TRN", OP_TRN, 3, 0, 1 ,1 ,0, 0, 0, &c_processor::op_trn }, // 15
{ "SDE", OP_SDE, 2, 1, 1, 1, 1, 0, 0, &c_processor::op_sde }, // 16
{ "SDU", OP_SDU, 2, 1, 1, 1, 1, 0, 0, &c_processor::op_sde }, // 17
{ "SZE", OP_SZE, 2, 1, 1, 1, 1, 0, 0, &c_processor::op_sze }, // 18
{ "SZU", OP_SZU, 2, 1, 1, 1, 1, 0, 0, &c_processor::op_sze }, // 19
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 1, &c_processor::op_nul }, // 1a
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 1, &c_processor::op_nul }, // 1b
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 1, &c_processor::op_nul }, // 1c
{ "NUL", OP_nul, 0, 0, 0, 0, 0, 0, 1, &c_processor::op_nul }, // 1d
...