[endian] Empty Base Class trouble implementing endian wrappers.

I've been working on Yuval's suggestion of (little|big|native)_endian wrappers, but ran into a problem. On fundamental types, the wrapper works fine, and Beman's integer_cover_operators made it easy to add support for integer operations. ( However, why does integer_cover_operators use operators<T> and not operators2<T,IntegerType> ? I needed to change that to solve an ambiguity error. ) The problem comes when wrapping my (newly reimplemented) exact type. In that case, deriving the wrapper from integer_cover_operators adds 1 byte : sizeof( long ) = 0x4 sizeof( boost::big_endian< long > ) = 0x4 sizeof( boost::exact<24> ) = 0x3 sizeof( boost::big_endian< boost::exact<24> > ) = 0x4 I could just have a get member function in the wrappers, but that loses much of the elegance. Any suggestions for solving this? ~ Scott McMurray P.S. exact came out quite nicely, imho: CHAR_BIT*sizeof( boost::exact<24>[2] ) = 48 CHAR_BIT*sizeof( boost::exact<24,signed,16>[2] ) = 64 CHAR_BIT*sizeof( boost::exact<32,unsigned>[2] ) = 64 CHAR_BIT*sizeof( boost::exact<8,unsigned,16>[2] ) = 32 ( std::numeric_limits< boost::exact<24> >::min() ) = -8388608 ( std::numeric_limits< boost::exact<24> >::min()-1 ) = 8388607 ( std::numeric_limits< boost::exact<24> >::max() ) = 8388607 ( std::numeric_limits< boost::exact<24> >::max()+1 ) = -8388608 ( std::numeric_limits< boost::exact<24,unsigned> >::min() ) = 0 ( std::numeric_limits< boost::exact<24,unsigned> >::max() ) = 16777215

me22 wrote:
I've been working on Yuval's suggestion of (little|big|native)_endian wrappers, but ran into a problem. On fundamental types, the wrapper works fine, and Beman's integer_cover_operators made it easy to add support for integer operations. ( However, why does integer_cover_operators use operators<T> and not operators2<T,IntegerType> ? I needed to change that to solve an ambiguity error. )
The problem comes when wrapping my (newly reimplemented) exact type. In that case, deriving the wrapper from integer_cover_operators adds 1 byte : sizeof( long ) = 0x4 sizeof( boost::big_endian< long > ) = 0x4 sizeof( boost::exact<24> ) = 0x3 sizeof( boost::big_endian< boost::exact<24> > ) = 0x4
I could just have a get member function in the wrappers, but that loses much of the elegance. Any suggestions for solving this?
Are you implementing the big_endian<T> class as holding a member of type T? If you do (that's the most logical way, I think), then it sounds most strange to me. Is it just one compiler that's causing problems? Have you tried on more than one compiler?

On 6/9/06, Yuval Ronen <ronen_yuval@yahoo.com> wrote:
Are you implementing the big_endian<T> class as holding a member of type T? If you do (that's the most logical way, I think), then it sounds most strange to me. Is it just one compiler that's causing problems? Have you tried on more than one compiler?
Yes, it's holding it as a member. I've tried it (with the same results) in g++ 3.3.6, 3.4.6, and 4.1.1. I just installed icc to try it with that, but I think there's a library mismatch or something with the rest of my system as I can't even get hello world to compile with it. I think it might just be a matter of the compiler getting lost in all the templates and being careful. When I try a simple test case with basically the same hierarchy and members it works fine: template <typename T, typename U> struct operators2 {}; template <typename T, typename U> struct int_wrapper_operators2 {}; template <size_t n_bits> struct exact : int_wrapper_operators2< exact<n_bits>, int > { char a[n_bits/8]; }; template <typename T> struct big_endian : int_wrapper_operators2< big_endian<T>, int > { T val; }; Resulting in ( sizeof( operators2<float,int> ) ) = 1 ( sizeof( int_wrapper_operators2<float,int> ) ) = 1 ( sizeof( long ) ) = 4 ( sizeof( big_endian<long> ) ) = 4 ( sizeof( exact<24> ) ) = 3 ( sizeof( big_endian< exact<24> > ) ) = 3 Is there possible a class deep down in operators<T,U> that is only templated on U? If there is, maybe the compile doesn't want to put the instance from integer_cover_operators< exact<24>, int > and integer_cover_operators< big_endian<exact<24> >, int > at the same address. I've also attached the problematic code as well, in the hopes that someone can find the problem or see whether it's gcc-specific. ( The integer_cover_operators.hpp is the same as Beman's, with the exception of using boost::operators<T,IntegerType> instead of boost::operators<T>. This solved an issue where std::numeric_limits< boost::exact<24> >::min()-1 was ambiguous. ) ~ Scott McMurray

me22 wrote:
On 6/9/06, Yuval Ronen <ronen_yuval@yahoo.com> wrote:
Are you implementing the big_endian<T> class as holding a member of type T? If you do (that's the most logical way, I think), then it sounds most strange to me. Is it just one compiler that's causing problems? Have you tried on more than one compiler?
Yes, it's holding it as a member.
I've tried it (with the same results) in g++ 3.3.6, 3.4.6, and 4.1.1. I just installed icc to try it with that, but I think there's a library mismatch or something with the rest of my system as I can't even get hello world to compile with it.
VC8 gives me sizeof( boost::exact<24> ) = 0x3 sizeof( boost::big_endian< boost::exact<24> > ) = 0x3 so maybe it's a gcc bug...
participants (2)
-
me22
-
Yuval Ronen