
First of all, I think we are confusing each other somewhere in these emails - I you, or you me, or both. Which, as you mention later down, does highlight the needs/problems. So if I talk past your some of your points, that might be why. Somehow, even in the confusion, I still think we are highlighting worthwhile points. On Tue, Jun 8, 2010 at 12:59 PM, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Gottlob Frege wrote:
On Tue, Jun 8, 2010 at 11:52 AM, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Gottlob Frege wrote:
It would be possible to also include the cases in which the input and output endiannesses are specified (the filter case), but those lead right back to confusion about the template argument order.
Technically, the output endianness would take the place of the int.
That doesn't fit the pattern because the result is an int, not a "big endian," for example. Hence the cast is to int first.
If you are explicitly converting with a from_type and a to_type, then (to me) the result is not actually an int, but a to_type. If you want to store it into an int, then cast it as one, or use to_type.raw().
But then you'd need a secondary cast, I suppose. ie
big j = endian_cast<big, little>(k); int i = reinterpret_cast<int>(endian_cast<big, little>(k));
Those aren't casts following the pattern of the new-style casts in the language.
Sorry if I wasn't clear, or don't understand - in my mind, k was typed/stored/declared as an int, it is holding a little-endian value that needs to be converted to big endian, then stored as another int (i). so int k = some_little_endian_int(); int i = reinterpret_cast<int>(endian_cast<big, little>(k)); or int i = endian_cast<big, little>(k).raw(); // interpret k as little, convert/cast to big, return raw (big) data.
wrapper.data() // raw data. or raw_data() or raw() or... wrapper.value() // converted to host *value*
I could live with raw() and host(). In fact, the copying conversion logic could actually be on that class:
w.convert<big_endian>(); w.convert<little_endian>(); w.raw();
Yes for the object-based approach. I like forcing everyone to use endian_cast<> but I can live with the above as well.
convert_from<big_endian>() is slightly nicer, but endian_cast<T, big_endian>() isn't really much worse (only 2 characters! (not really...))
Actually, you're comparing those wrong. convert_from<big_endian>() means convert from big endian to host order. The equivalent cast requires knowing the host order: endian_cast<T, native_endian>(). I like the former better because it reads nicely, not just that it is shorter.
to me endian_cast<int>(e) takes a known endian type and converts to a host int. ie e was previously declared to be a big_endian or something. Thus endian_cast<int, big_endian>(i) takes an int (I suppose), reinterprets it as a big_endian, then converts (swaps if necessary) it to an int. The 'int' in the cast is for the return type, not the input type of i. I wonder if this is the source of confusion? If i is not an int, (in particular, if i is an endian type?) I'm not sure what it should do. And, as mentioned endian_cast<little_endian, big_endian>(i) takes an int, reinterprets it as a big_endian, converts it to a little_endian, returning a little_endian. endian_cast<little_endian, big_endian>(i).raw(); as above, returning an "int". At least an int by declaration and storage.
The benefit of the latter is consistency and explicitness.
Is the above 4 cases clear/consistent/explicit? It wasn't completely formed in my mind at the start of this all, so thanks for the back-and-forth.
Notice how easy it was to get wrong! It is also not consistent with the normal casts.
Yes! I'm not sure where we diverged, but we have. :-) Tony