On Saturday, 27 February 2016 20:55:54 UTC+2, Marcel Mueller wrote:
> Let's have a dispatch table of an assembler.
>
>
> /// Entry of the OP code lookup table, POD, compatible with binary_search().
> /// @tparam L maximum length of Name.
> template <size_t L>
> struct opEntry
> { char Name[L]; ///< OP code name
> void (Parser::*Func)(int);///< Parser function to call, receives the
> agrument below.
> int Arg; ///< Arbitrary argument to the parser function.
> };
I see you use string literals to initialize 'Name' so I don't
understand why there is that mutable array and that L, do you want
to dynamically modify it? String literal is guaranteed to live
forever so you could use pointer to it or pointer and length pair.
>
> /// Map with opcode tokens, must be ordered.
> const Parser::opEntry<8> Parser::opcodeMap[] =
> { {"add", &Parser::assembleADD, Inst::A_ADD }
> , {"and", &Parser::assembleADD, Inst::A_AND }
> , {"asr", &Parser::assembleADD, Inst::A_ASR }
> , {"bpkt", &Parser::assembleSIG, Inst::S_BREAK }
> , {"bra", &Parser::assembleBRANCH, false }
> //...
> };
>
>
> Each parser function takes an (optional) argument. The type is fixed to
> int in this example. But this is not safe. Mostly the type is some enum.
> But each function takes another argument type, and of course, the third
> argument in the table must match the argument type of the function.
Use some type-safe variant then instead of 'int' for example Boost.Variant,
QVariant, Eggs.Variant.
>
> For type safe operation it would be nice to have a type like
>
>
> template <size_t L, typename P>
> struct opEntry
> { char Name[L]; ///< OP code name
> void (Parser::*Func)(P);///< Parser function to call, receives the
> agrument below.
> P Arg; ///< Arbitrary argument to the parser function.
> };
That would not be issue if P was a variant not template argument.
'boost::variant<paramtype1,paramtype2,paramtype3>'. You must know
anyway all the different types of parameters when you initialize
that 'opcodeMap' of yours. Btw words like "Map" and "List" may be
misleading in name of variable since readers sometimes assume
underlying container.
>
> But this does not work since each line of Parser::opcodeMap[] has
> another type P in general and all of these structures must fit into the
> same storage. Of course, there is only a solution when sizeof(P) has an
> upper limit, since this is similar to a union.
No ... union is not type-safe, it is type-punning.
>
> Could this be expressed type safe in C++11, without the need to deal
> with pointers, new and delete for each line?
Unfortunately the 'variant' is not in C++11. The proposal of it
N4542 added default empty state to it while 'boost::variant' has
never-empty guarantee (unless you put 'boost::blank' as first type
that is). Huge language lawyer shitstorm and lot of controversy
later it has transformed into P0088R1 so maybe in C++17 we will have
it.