Boost logo

Boost :

From: felipe (pbr_at_[hidden])
Date: 2005-08-11 10:10:45


> Date: Thu, 11 Aug 2005 09:00:20 -0400
> From: christopher diggins <cdiggins_at_[hidden]>
> Subject: Re: [boost] alignment problem in proposed any alternative
> To: boost_at_[hidden]
> Message-ID: <004c01c59e74$a17a7800$2b792518_at_heronnest>
> Content-Type: text/plain; format=flowed; charset=iso-8859-1;
> reply-type=original
> ----- Original Message -----
> From: "felipe" <pbr_at_[hidden]>
> To: <boost_at_[hidden]>
> Sent: Thursday, August 11, 2005 4:09 AM
> Subject: Re: [boost] alignment problem in proposed any alternative
>
>> Nope, this is totally wrong! chars and arrays of type char are
>> generally
>> the least aligned objects. You can demonstrate that this doesn't work
>> with something like this:
>>
>> void blah()
>> {
>> char c[/* some number */];
>> any<8> a((double)1.0);
>> std::cout << &a << std::endl;
>> }
> That code is completely misleading, yhe question is not what the address
> of
> a is!
>

Well, let me clarify:

/*############ BEGIN ########*/
#include <iostream>
#include <boost/type_traits.hpp>

template<int buffer_size>
struct any {
   char c; // this offsets buffer by one-byte.. because for the
           // compiler, chars only need byte alignment
   char buffer[buffer_size];
   // ...
   template<typename T>
   any(const T& x) {
     if (boost::is_pod<T>::value &&
         (sizeof(T) <= buffer_size)) {
       memcpy(buffer, &x, sizeof(T));
     }
     else {
       // new and stuff
     }
   }
};

int main(int argc, char **argv)
{
   any<8> blah((double)1.0);
   std::cout << (void *)&blah.buffer << std::endl;
   return 0;
}

/*##### END ########*/

Output of the program on Pentium/Win2k/Visual C++ 6.0: 0x22ef01

This is obviously NOT a good place for a double, unless you are going to
memcpy everything, which would be a needlessly inefficient design. Right,
the Pentium lets me slide (with some extra instructions to keep away idle
cycles), but don't try it on an Alpha!

Have you not read the articles by Alexandrescu in CUJ? These are pretty
old and yet they explore all of this stuff. What you should do is make
the buffer a union of a minimal size object (e.g. your char array) and a
minimum alignment object (e.g. a double in the example above). The
compiler then adjusts alignment for the latter, while guaranteeing space
for the former.

Another thing, your proposal shies away from objects with constructors,
etc. Why? You can use the placement new operator and get a much cleaner
implementation. You know, something like this:

   template<typename T>
   any(const T& x) {
     ..
     new(&buffer[0]) T(x); // instead of memcpy

hope this helps

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/m2/

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