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.
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.