Boost logo

Boost :

Subject: Re: [boost] [endian] endian flip and endian domain
From: Stewart, Robert (Robert.Stewart_at_[hidden])
Date: 2010-06-08 11:52:00


Gottlob Frege wrote:
>
> - I agree that the operators on an endian type are dangerous and
> should be separated. (I also think operators on atomics are
> dangerous, but that's another story.)

Dangerous? My only concern is that they are inefficient and can lead one to write unnecessarily inefficient code.

> - I think we should consider that read on endian types is dangerous -
> that is what the 'function-style' seems to be saying. ie an endian
> type that I can read from will be read from multiple times and be
> inefficient. But useful at times. So separated?

We've all agreed that they should be separate for reasons of efficiency and syntax.

> - so am I suggesting a base endian type that can't even be
> read? Possibly.

That's interesting.

> Note that the endian_cast<> discussion mentioned that it didn't follow
> the cast<> syntax exactly, because return type and parameter type are
> the same. This is essentially because we want to take the source int
> and cast it to an endian, then cast it back to an int, all because we
> didn't/couldn't define our source value as an endian type.
> ie
>
> int j = from_big_endian_file();
> int i = endian_cast<big>(j);
>
> should really be (if using types)
>
> big_endian_int j = from_big_endian_file();
> int i = endian_cast<int>(j);
>
> or
>
> int i = endian_cast<int>(reinterpret_cast<big_endian_int>(j));
>
> That's just too much to type. (And not necessarily the right names,
> but leave that aside for now. I'm purposely using 'big_endian_int'
> instead of trying to use a decent name, to avoid the naming
> discussions)

That's an interesting view.

> So, I'm not sure if this can work out, but if we decide that
> endian-types and type-safety is important, then endian_cast<> (or

We have.

> convert, or...) should *only take an endian type*.

That's an interesting way to view endian_cast.

> Then we get
>
> big_endian_int j = from_big_endian_file();
> int i = endian_cast<int>(j); // OK
>
> int k = from_big_endian_file();
> int i = endian_cast<int>(k); // FAILS - not sure endian type for k
>
> but then allow specifying the type for k:
>
> int i = endian_cast<int, big_endian_int>(k); // OK - k is
> reinterpreted as big_endian_int

The latter is a departure from the new-style casts. This harkens back to the earlier notion of swap<to,from>() that I suggested and Tomas dismissed because of the confusion that can arise over template argument order. However, by naming the function "endian_cast," you sidestep that problem because the "to" type would always be first in keeping with the normal cast use case.

Let's see how this looks in code (I'm going to assume "endian_wrapper" as the base class name for exposition):

   template <class T, class Endianness>
   T
   endian_cast(endian_wrapper<Endianness> _wrapped)
   {
      T const result(
         swap_to_host_order<Endianness>(_wrapped.value()));
      return result;
   }

   template <class T, class Endianness>
   T
   endian_cast(T _wrapped)
   {
      T const result(swap_to_host_order<Endianness>(_value));
      return result;
   }

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.

Notice that endian_wrapper<> needed a means to get the value. I don't see the value of a wrapper type that specifies the endianness but gives no means to access the value.

> Does this make sense? It's still a bit vague in my mind, but I'm just
> wondering if we can somehow manage to use the same functions and
> syntax in both the typed and untyped scenarios.

I think I understood you and it seems rather interesting. It is useful to make the source endianness explicit in the call which this approach does by requiring either a wrapper type with endianness or a template argument, but that is also made explicit by the other function-based interfaces we've discussed.

If the value to be converted using something like endian_cast is a field in a struct, and that structure's definition is provided outside the client program, then the field will likely be a built-in type, not an endian_wrapper. That means the conversion is from T to T. convert_from<big_endian>() seems better than endian_cast<T,big_endian>(). IOW, I don't think endian_cast can be extended helpfully as you've suggested. Instead, endian_cast<int>(make_endian<big_endian>(t)) would be needed and convert_from<big_endian>(t) is much clearer. (Perhaps the latter would be implemented using the former.)

That concern aside, I do like your suggested use of endian_cast with the endian_wrapper type.

_____
Rob Stewart robert.stewart_at_[hidden]
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk