
Terry wrote:
swap_in_place still needs a reinterpret_cast too to convert from the 'char * buf' assembled from the hypothetical TCP stream.
Robert Stewart wrote:
Not quite. As discussed in a separate post, a static_cast is sufficient and there's only one cast needed. That's still less ugly. (Since buf is a void * in the snipped code, static_cast would work for your casts, too.)
'buf' must be a pointer to "something". The void* is just masking what is really analagous to a reinterpret_cast. void* is just as ugly as reinterpret_cast. Maybe more so.
What bugs me is that 'buf' doesn't point to a 'T' yet. It points to a half-baked 'T'. Only after one calls swap_in_place() is the object really a 'T'.
That would apply to floating point, certainly. However, for integer types, your statement is false. Before the swap, they are still integers, they just don't have the desired value.
I disagree. Physically, they are compatible, but logically, they are different. I think the logical view matters more.
Even in the object-based approach, the object isn't a proper T until you access it and the swap occurs. The implicit swap veneer just gives you the impression that it is already in the desired form.
An endian<X, T> is not the same as a T. Even endian<native, T> must be converted to a T before you can operate on it. The veneer is important, because it works like a T, without actually being a T. I think that subtle distinction is important and is the primary motivation for type-based endian. I object to your use of the word "swap" though. My type-based approach does a reverse_copy, not a swap. This distinction is the fundamental topic of this discussion. When T is not integral, the distinction becomes more important. Although I have found endian<big, double> to be useful in the past. I wouldn't recommend that anyone actually do that (though I wouldn't prohibit it either). For production systems, would prefer that messages contain something like... #pragma pack(push, 1) template<endian_t E> class ieee754::binary64 { // storage in ieee754 format. public: binary64(); // 0.0 in ieee format binary64(double x); // converts from native double to ieee format operator double() const; convert ieee format to native double binary64& operator=(double x); // convert native double to ieee format }; struct Message { typedef interface::ieee754::binary64<big> Double; Double x, y, z; }; #pragma pack(pop) terry