alignment problem in proposed any alternative

In the boost::any alternative implementation being developed by Pablo Aguilar and myself (latest version at http://www.codeproject.com/cpp/dynamic_typing.asp ) we have run into a problem of alignment with no obvious answer. We are trying to do the following: struct any { void* table; void* object; ... template<typename T> any(const T& x) { table = any_detail::get_table<T>::get(); if (sizeof(T) <= sizeof(void*)) { if (new(&object) T(x) != &object) { throw runtime_error("can not align the data type ... pigs must be flying"); } } } else { object = new T(x); } } The question I have is whether in practice though are there are any compilers which have stricter alignment requirements on small types (<= sizeof(void*)) than a void pointer. In other words, is it possible with any known compiler to actually throw the runtime error ? Unfortunately there is another problem, I am not an expert in interepreting the standard, but AFAICT placement new is guaranteed to return a pointer to properly aligned memory (3.7.3.1 / 2) which I leverage to check that alignment occured. Apparently not every STL implementation does in fact do that (I believe at least dinkumware is guilty of that). Thanks in advance for your help! Christopher Diggins http://www.cdiggins.com

----- Original Message ----- From: "christopher diggins" <cdiggins@videotron.ca> To: "Boost mailing list" <boost@lists.boost.org> Sent: Wednesday, August 10, 2005 1:30 AM Subject: [boost] alignment problem in proposed any alternative
The question I have is whether in practice though are there are any compilers which have stricter alignment requirements on small types (<= sizeof(void*)) than a void pointer. In other words, is it possible with any known compiler to actually throw the runtime error ?
Now a moot point, see below.
Unfortunately there is another problem, I am not an expert in interepreting the standard, but AFAICT placement new is guaranteed to return a pointer to properly aligned memory (3.7.3.1 / 2) which I leverage to check that alignment occured. Apparently not every STL implementation does in fact do that (I believe at least dinkumware is guilty of that).
Apparently I am wrong about this! 18.4.1.3 provides an exception. (I wonder why I missed the exception 15 chapters later?) Anyway it turns out we can guarantee alignment by simply using a char buffer. According to 3.9/2 the following automatically has no alignment problems: template<int buffer_size> struct any { char buffer[buffer_size]; ... template<typename T> any(const T& x) { if (boost::is_pod<T>::value && (sizeof(T) <= buffer_size)) { memcpy(buffer, &T, N); } else { // new and stuff } } } Christopher Diggins http://www.cdiggins.com

On 08/10/2005 09:27 AM, christopher diggins wrote: [snip]
Anyway it turns out we can guarantee alignment by simply using a char buffer. According to 3.9/2 the following automatically has no alignment problems:
template<int buffer_size> struct any { char buffer[buffer_size]; ... template<typename T> any(const T& x) { if (boost::is_pod<T>::value && (sizeof(T) <= buffer_size)) { memcpy(buffer, &T, N); Wouldn't this fail to update the refcount if T was shared_ptr or weak_ptr? } else { // new and stuff } } }

----- Original Message ----- From: "Larry Evans" <cppljevans@cox-internet.com> To: <boost@lists.boost.org> Sent: Wednesday, August 10, 2005 12:10 PM Subject: Re: [boost] alignment problem in proposed any alternative
On 08/10/2005 09:27 AM, christopher diggins wrote: [snip]
Anyway it turns out we can guarantee alignment by simply using a char buffer. According to 3.9/2 the following automatically has no alignment problems:
template<int buffer_size> struct any { char buffer[buffer_size]; ... template<typename T> any(const T& x) { if (boost::is_pod<T>::value && (sizeof(T) <= buffer_size)) { memcpy(buffer, &T, N); Wouldn't this fail to update the refcount if T was shared_ptr or weak_ptr?
You are correct, but they aren't POD types so we would be safe. I can't help but wonder if this doesn't somehow imply placement new will work just as well. if ((sizeof(T) <= buffer_size)) { new(buffer) T(x); By the way, I made a small mistake originally it should have been memcpy(buffer, &x, N); Christopher Diggins http://www.cdiggins.com

christopher diggins wrote:
Anyway it turns out we can guarantee alignment by simply using a char buffer. According to 3.9/2 the following automatically has no alignment problems:
template<int buffer_size> struct any { char buffer[buffer_size];
Here buffer will only meet the alignment requirements of char. IIUC, char[buffer_size] generates properly aligned storage for something of size buffer_size only when used in a new expression: char * buffer = new char[buffer_size]; Anyway, perhaps you could into boost::aligned_storage for your purposes. Regards, João Abecasis

On 08/11/2005 07:28 AM, Joao Abecasis wrote:
christopher diggins wrote: [snip]
template<int buffer_size> struct any { char buffer[buffer_size]; [snip] char[buffer_size] generates properly aligned storage for something of size buffer_size only when used in a new expression: [snip] Anyway, perhaps you could into boost::aligned_storage for your purposes. Couldn't the code from boost::detail::make_storage defined in:
http://cvs.sourceforge.net/viewcvs.py/boost/boost/boost/variant/variant.hpp be copied and modified somehow to solve the problem? It uses boost::aligned_storage.

On 08/12/2005 01:31 PM, Larry Evans wrote:
On 08/11/2005 07:28 AM, Joao Abecasis wrote: [snip]
Anyway, perhaps you could into boost::aligned_storage for your purposes.
Couldn't the code from boost::detail::make_storage defined in: OOPS. That's for variant, not for any. Sorry :(

On Wed, 10 Aug 2005 09:30:00 +0400, christopher diggins <cdiggins@videotron.ca> wrote: []
The question I have is whether in practice though are there are any compilers which have stricter alignment requirements on small types (<= sizeof(void*)) than a void pointer. In other words, is it possible with any known compiler to actually throw the runtime error ?
You can probably force do the same thing as malloc() from glibc does and use a default alignment of 8 for 32bit and 16 for 64bit platforms: Alignment: 2 * sizeof(size_t) (default) (i.e., 8 byte alignment with 4byte size_t). This suffices for nearly all current machines and C compilers. However, you can define MALLOC_ALIGNMENT to be wider than this if necessary. -- Maxim Yegorushkin
participants (4)
-
christopher diggins
-
Joao Abecasis
-
Larry Evans
-
Maxim Yegorushkin