On 2016-04-04 14:54, Peter Dimov wrote:
Gavin Lambert wrote:
If you have API that can take a void* or char* (or other block-of-bytes-of-appropriate-size) and then reinterpret this as a big-endian or little-endian float/double/longdouble (returning the native representation), then this can work and is a useful function. Similarly taking a native float/double/longdouble and writing it to a block-of-bytes in a specified endian format.
"Little-endian float" is not enough information. Floating point formats are not fully described by their endianness. (Neither are integer formats in principle, but in practice they are.)
Do you mean word-granular endianness here? I would say, it's just another type of endianness.
Apart from that, I agree. char[4] /* IEEE 32 bit little endian float */ <-> float is a correct interface. Or even uint32_t <-> float.
uint32_t float_to_bits( float x ); float float_from_bits( uint32_t v );
If you have that, you can then byteswap the unit32_t to your heart's content, even though the correct interface there is also char[4] /* little endian 32 bit */ <-> uint32_t.
As a Boost.Endian library user, until the first style of API is implemented you can work around it by doing endian swaps on unsigned integers only, and using a bitwise_cast-equivalent to convert between the floating-point values and unsigned integers of appropriate size.
Something like that, yes, but what I'm suggesting is not a bitwise cast. There need not be any correspondence between the uint32_t bits and the float bits, because the uint32_t is IEEE, and the float is native.
I think it's not Boost.Endian's job to deal with FP implementations. Or integer implementations, for that matter. The interface can be defined to require a certain implementation of float or to simply ignore the implementation and consider input as opaque sequence of bytes. The implementation of that interface should just reorder bytes in that sequence, as requested, and do nothing more than that.
Technically, this could also be true for integers; the char[4] representation is 32 bit with no padding and no trapping, and the uint32_t (which would have to be uint_least32_t) may have them.
uint32_t cannot have traps or padding bits, so no problem there. If the interface uses this type then it restricts the library to architectures that can provide such a type, which realistically should be fine, but probably would not fit the C++ standard. A more generic interface would just avoid using integers as a storage of bits and just use a byte buffer for that (i.e. and array of char/unsigned char/signed char or input/output iterators of such value type or some such).
(Although this assumes CHAR_BIT == 8. I'm not sure what is the right interface when CHAR_BIT is 32.)
If a raw buffer is used to store bits then there is no problem as any C++ type has size of an integer number of chars. This may pose interoperability issues between platforms with different values of CHAR_BIT, but I'm inclined to think this is not a problem of endianness per se, but a problem of portable (de)serialization, which is a much wider problem than just endianness management (which, by definition, operates whole bytes - which are chars in C++).