
On 09/07/2011 04:04 PM, Vicente J. Botet Escriba wrote:
What about enums? Could we use enums as underlying type of boost::endian<>?
That would be nice, but it seems of limited use in C++03; Isn't the actual size of an enum unspecified and compiler dependent? Scoped enums in C++0x, with their ability to specify the underlying type, seems much more usable.
struct UdpHeader { uint16_t source_port; // big uint16_t destination_port; // big uint16_t length; // big uint16_t checksum; // big }; // UdpHeader
I'm curious what you mean when you say UDT. Do you want to be able to say endian<big, UdpHeader>? That seems like a much more difficult problem and way beyond the scope of what Beman's library is trying to do. By the way, it's exactly this type of ubiquitous system struct that makes me think these something like the endian types in Beman's library should become part of the the C++ (and C) standard. It would allow programmers to stop worrying about these issues when dealing with external data.
quantity<si::length, boost::int_least32_t> x; // little
I would do: quantity<si::length, little32_t> The above scheme (defining the UDT in terms of the endian types instead of defining an endian type in terms of a UDT) should work in many cases. In fact, it seems like the preferred (or even required) approach in many cases. A small amount of testing seems to indicate that this works fairly well with the current version of Boost.Endian. I was worried that code like the following wouldn't compile at all because the compiler would think QI, QL, and QB were different incompatible types. But Boost.Units seems to provide the right magic to make the following work as desired. Unfortunately, Boost.Endian's lack of implicit conversion to the endian types limits how well this works (see comment in main() below) #include <boost/units/systems/si.hpp> #include <boost/endian/integers.hpp> #include <cstdio> using namespace boost::units; using namespace boost::endian; int main() { typedef quantity<si::length, int> QI; typedef quantity<si::length, big32_t> QB; typedef quantity<si::length, little32_t> QL; QI qi(0x11223344 * si::meters); QL ql(0x22334455 * si::meters); QB qb(0x33445566 * si::meters); printf("%08x (qi)\n", *((int*)(&qi))); printf("%08x (ql)\n", *((int*)(&ql))); printf("%08x (qb)\n", *((int*)(&qb))); qi = ql; printf("%08x (qi=ql)\n", *((int*)(&qi))); qi = qb; printf("%08x (qi=qb)\n", *((int*)(&qi))); // These: // qb = qi; // ql = qi; // // don't work because the following fail: // BOOST_STATIC_ASSERT(( // boost::is_convertible<int, big32_t>::value == true)); // BOOST_STATIC_ASSERT(( // boost::is_convertible<int, little32_t>::value == true)) // // Likewise for qb=ql and ql=qb; // // To write to endian types, you have to use the much more clunky: ql = QL(qb.value() * si::meters); printf("%08x (ql=qb)\n", *((int*)(&qi))); } On a little endian machine, the above should produce: 11223344 (qi) 22334455 (ql) 66554433 (qb) 22334455 (qi=ql) 33445566 (qi=qb) 33445566 (ql=qb) Note that if the endian types supported something like: big32_t x = 0x11223344; Then all the failed cases would work as well. Beman, if you're reading this, do you consider the above dangerous and prefer requiring the explicit conversion (i.e. big32_t x = big32_t(0x11223344)), or is adding support for implicit conversion something that you wouldn't find objectionable?