Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

serialize any data type as vector<uint8_t> - use reinterpret_cast?

I didnt find anything directly related in searching, so please forgive if this is a duplicate.

What I am looking to do is serialize data across a network connection. My approach is to convert everything I need to transfer to a std::vector< uint8_t > and on the receiving side unpack the data into the appropriate variables. My approach looks like this:

template <typename T>
inline void pack (std::vector< uint8_t >& dst, T& data) {
    uint8_t * src = static_cast < uint8_t* >(static_cast < void * >(&data));
    dst.insert (dst.end (), src, src + sizeof (T));
}   

template <typename T>
inline void unpack (vector <uint8_t >& src, int index, T& data) {
    copy (&src[index], &src[index + sizeof (T)], &data);
}

Which I'm using like

vector< uint8_t > buffer;
uint32_t foo = 103, bar = 443;
pack (buff, foo);
pack (buff, bar);

// And on the receive side
uint32_t a = 0, b = 0;
size_t offset = 0;
unpack (buffer, offset, a);
offset += sizeof (a);
unpack (buffer, offset, b);

My concern is the

uint8_t * src = static_cast < uint8_t* >(static_cast < void * >(&data));

line (which I understand to do the same as reinterpret_cast). Is there a better way to accomplish this without the double cast?

My naive approach was to just use static_cast< uint8_t* >(&data) which failed. I've been told in the past that reinterpret_cast is bad. So I'd like to avoid it (or the construct I have currently) if possible.

Of course, there is always uint8_t * src = (uint8_t *)(&data).

Suggestions?

like image 850
ezpz Avatar asked Jul 01 '10 20:07

ezpz


1 Answers

My suggestion is to ignore all the people telling you that reinterpret_cast is bad. They tell you it is bad, because it's generally not a good practice to take the memory map of one type and pretend that it's another type. But in this case, that is exactly what you want to do, as your entire purpose is to transmit the memory map as a series of bytes.

It is far better than using a double-static_cast, as it fully details the fact that you are taking one type and purposefully pretending that it is something else. This situation is exactly what reinterpret_cast is for, and dodging using it with a void pointer intermediary is simply obscuring your meaning with no benefit.

Also, I'm sure that you're aware of this, but watch for pointers in T.

like image 196
jdmichal Avatar answered Oct 05 '22 23:10

jdmichal