In C++, consider using
std::bitset instead.
Also, use named constants for your field widths, to reduce mainentance effort.
Also in C++, use namespaces instead of tagging your names like that.
Oh, and don't put 'Type' into class names unless you really mean it - i.e., you're doing some kind of meta-typing thing where the objects themselves describe some kind of type. Classes are *always* types, so it's redundant and potentially confusing (because experienced programmers may be looking for that non-existent meta-typing).
namespace nsl { const int[] masks = { // field widths in the middle column // v 1 << 8 - 1, 1 << 4 - 1, 1 << 4 - 1 }; // Or change to 8, 8, 8 if needed :) const int[] positions = { 0, instruction_width, instruction_width + arg1_width // etc. for more. }; const int size = instruction_width + arg1_width + arg2_width; // You shouldn't need to pad manually - the compiler's struct alignment // should take care of that automatically. struct Opcode { enum field { instruction, arg1, arg2 }; std::bitset<size> storage; OpcodeType(int i_value, int a1_value, int a2_value) { (*this)[instruction] = i_value; (*this)[arg1] = a1_value; (*this)[arg2] = a2_value; } explicit OpcodeType(DWord d) : storage(static_cast<unsigned long>(d)) {} int& operator[](field f) { return (storage >> positions[f]) & masks[f]; } int operator[] const(field f) { return (storage >> positions[f]) & masks[f]; } DWord toDWord() { return static_cast<DWord>(storage.to_ulong()); } };}
This way, conversion to and from DWords is as simple as a little casting (assuming they're the same size as unsigned long - otherwise you'll want to be a little more rigorous), and if the field widths change, all you need to change are the mask values. (If the *order* changes, more work is involved, but I really don't think there's a way around that.) Instead of accesing fields of the struct with member selection, you access them like "elements", using the subscript operator (and providing one of the enumeration values as a subscript). Thus 'myOpcode.arg1' becomes 'myOpcode[Opcode::arg1]'.