
On 24/05/08 05:45 AM Beman Dawes wrote:
Neil Mayhew wrote:
The areas that I am interested in seeing more work done on are (1) making constructors "conditional" and (2) adding a bit-range access method.
* Should there be a way (#ifdef? separate class?) to provide an interoperable version that meets C++03 POD requirements, so endian objects can be put in unions? Is that what you mean by (1)?
Yes, this is what I meant. I was thinking that the most elegant solution would be to have a base class that contains everything except the constructors, and a derived class that adds the constructors (I think this was in a post in 2006). The typedefs to big32_t etc. would then be #if'd to correspond to the POD or non-POD classes as desired. I think this is better than putting the #if's around the constructors themselves.
Do you have a proposed design for bit-range access?
I was thinking of adding methods to read and write the given bits within the value: value_type endian::bits(std::size_t offset, std::size_t length) const; value_type endian::bits(std::size_t offset, std::size_t length, value_type value); Making these template methods with offset and length being template arguments might allow for more compile-time unrolling, but since these methods just do shifting and masking, the compiler will probably do all the needed optimization anyway. A better design might be to specialize Bitfield to accept endians, although I haven't studied Bitfield enough yet to see how well this would work.
What is the use case or motivation for bit-range access?
A packed binary structure like the following. The numbers are lengths in bits, and the total length is 24 bits (ie 3 bytes): +------------+-----------+------------+ | field_a:6 | field_b:4 | field_c:14 | +------------+-----------+------------+ This may look contrived, but I have seen plenty of things similar to this in protocols and data files. As part of a bigger struct, this would be implemented using endian::bits as follows: struct packet { ubig24_t abc; uint_least32_t field_a() const { return abc.bits(0, 6); } uint_least32_t field_b() const { return abc.bits(6, 4); } uint_least32_t field_b() const { return abc.bits(10, 14); } uint_least32_t field_a(uint_least32_t v) { return abc.bits(0, 6, v); } uint_least32_t field_b(uint_least32_t v) { return abc.bits(6, 4, v); } uint_least32_t field_b(uint_least32_t v) { return abc.bits(10, 14, v); } }; If the design used Bitfield instead, there would be one access method for both read and write, which would return by value a Bitfield on abc. However, the method would need to have both const and non-const versions, returning a const and non-const Bitfield respectively. Unfortunately, the Bitfield can't be made a part of the struct because it would take up space, breaking the mapping of the memory. So there would be an inconsistency with the syntax for accessing other (non-bit) fields within the structure, ie with and without parens, but I can live with that. --Neil