Search code examples
c++intbitunions

A class containing int in different Bytes?


I would like to come up with a Record class, which containing a int but it could be a int64_t, int32_t, int16_t, int8_t.
But I had problem, when I want to read data out of this Record object.


Assumption in our context:
We know which int we want to save.
We have to pay attention to the performance of getValue() such function and the size of such class or union.

I would try 3 implementation at in context (very dummies).
1.The first implementation:

class Record{
  int64_t value;
  unsigned int bytes; // number of bytes, in context 1 or 2 or 3 or 4 representing int8_t, int16_t, int32_t, int64_t

  int64_t getValue() { return value; }
  unsigned int getNumByte() { return bytes; }
}

I would try to call getValue() and getNumByte() then to cast the value to the correct type, like if (getNumByte() == 1) auto value = (int8_t getValue()).


2.Second: Using a template.

template <class T> 
class Record{
  T value;
  T getValue() { return value; }
}

3.Third: Using a union:

union Record {
  int64_t int64;
  int32_t int32;
  int16_t int16;
  int8_t int8;
};

My question:
Regarding this context, which implementation is better?
When they are all not so optimal, which approach would you come up with?


The reason for this question: It was a Record for char*. So in this situation would a char* value with a unsigned int length make sense. I want to switch to a int situation and have this problem.


Solution

  • The template is optimal in the sense that it will always be the same size as the underlying type, and will be optimized away. A few small changes.

    template <class T> 
    class Record {
        T value;
      public:
        const T& getValue() const { return value; }
    }
    

    However this solution does not allow you to have a container of Records with different template arguments, and makes serialization/deserialization code harder to work with.

    Furthermore, if this code works for you, then ask yourself what purpose this "Record" serves? I would just use the underlying type itself.