Topic: A humble attempt to suggest alignment support for C++
Author: Alexander Terekhov <terekhov@web.de>
Date: Sat, 13 Jul 2002 19:31:54 GMT Raw View
Gabriel Dos Reis wrote:
>
> Alexander Terekhov <terekhov@web.de> writes:
>
> [...]
>
> | > I'm not (yet) convinced that a simple type specifier is necessary: A
> | > library solution may suffice:
> | >
> | > std::aligned_storage<T>::type buffer[count]
> |
> | aligned_storage_pod(T) buffer; // implementation-defined POD type
>
> std::aligned_storage<T>::type is such a POD. What else am I missing?
Uhmm. You wrote:
http://groups.google.com/groups?selm=m3bs9gu4hy.fsf%40merlin.nerim.net
: requirement that std::aligned_storage<T>::type be a synonymous
: for char[sizeof (T)] with the additional attribute that it is suitably
: aligned.
I personally don't need it to be "synonymous for char[sizeof (T)]"
with some magic [w.r.t. conventional chars] "additional attribute
that it is suitably aligned".
An 'opaque' POD type would be 'sufficient', I think.
regards,
alexander.
P.S. http://groups.google.com/groups?selm=ad35eb%24mpa%241%40news.tuwien.ac.at
("From: Christopher Eltschka (celtschk@web.de)")
"....
Solution #4:
Provide a built-in "class template" align<T> with the following
properties:
a) align<T> has the samme alignment restrictions as T
b) align<T> has the smallest size compatrible with those alignment
restrictions (i.e. sizeof(align<T>) gives the alignment of T)
c) align<T> is POD
...."
aligned_storage_pod(T) is nothing [b)-above and "void"-max_align aside]
but a sort of "typeof" version of >>built-in "class template" align<T>.<<
Well, I've noticed this message from Christopher Eltschka AFTER I've sent
my reply to your "synonymous for char[sizeof (T)]" article.
P.P.S. typeof(x {,aligned_storage_pod|cv-and/or-ref-preserving|whatever})?
http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Alignment.html#Alignment
http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Typeof.html#Typeof
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@merlin.nerim.net>
Date: 14 Jul 2002 01:51:09 GMT Raw View
"Baugereau" <baugereau@ifrance.kom> writes:
| I quite agree but you often want to specify a different alignment for
| different allocations of the same type
| std::aligned_storage<T,128>::type buffer[count] might be better (but I guess
| we can have a default parameter).
Yes, default template-argument makes it work with user supplied (as
opposed to compiler-deduced) alignment.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@codesourcery.com>
Date: Sun, 14 Jul 2002 09:56:23 GMT Raw View
Alexander Terekhov <terekhov@web.de> writes:
| Gabriel Dos Reis wrote:
| >
| > Alexander Terekhov <terekhov@web.de> writes:
| >
| > [...]
| >
| > | > I'm not (yet) convinced that a simple type specifier is necessary: A
| > | > library solution may suffice:
| > | >
| > | > std::aligned_storage<T>::type buffer[count]
| > |
| > | aligned_storage_pod(T) buffer; // implementation-defined POD type
| >
| > std::aligned_storage<T>::type is such a POD. What else am I missing?
|
| Uhmm. You wrote:
|
| http://groups.google.com/groups?selm=m3bs9gu4hy.fsf%40merlin.nerim.net
|
| : requirement that std::aligned_storage<T>::type be a synonymous
| : for char[sizeof (T)] with the additional attribute that it is suitably
| : aligned.
|
| I personally don't need it to be "synonymous for char[sizeof (T)]"
| with some magic [w.r.t. conventional chars] "additional attribute
| that it is suitably aligned".
|
| An 'opaque' POD type would be 'sufficient', I think.
Well, "an opaque POD type" is also a magic.
And if all you want is to have a POD type, then you can safely ignore
about the additional alignment atttibute.
[...]
| http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Alignment.html#Alignment
I'll well aware of this. That might be one of the reason why I'm not
convinced of the need to introduce a core language extention.
Actually, I'm envisioning support for "alignment" storage in the
library having two components:
1) std::aligned_storage<T, N>::type;
2) std::type_traits<T>::alignment.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: terekhov@web.de (Alexander Terekhov)
Date: 15 Jul 2002 02:05:14 GMT Raw View
Gabriel Dos Reis <gdr@codesourcery.com> wrote in message news:<m3y9cf2yqb.fsf@merlin.nerim.net>...
> Alexander Terekhov <terekhov@web.de> writes:
>
> | Gabriel Dos Reis wrote:
> | >
> | > Alexander Terekhov <terekhov@web.de> writes:
> | >
> | > [...]
> | >
> | > | > I'm not (yet) convinced that a simple type specifier is necessary: A
> | > | > library solution may suffice:
> | > | >
> | > | > std::aligned_storage<T>::type buffer[count]
> | > |
> | > | aligned_storage_pod(T) buffer; // implementation-defined POD type
> | >
> | > std::aligned_storage<T>::type is such a POD. What else am I missing?
> |
> | Uhmm. You wrote:
> |
> | http://groups.google.com/groups?selm=m3bs9gu4hy.fsf%40merlin.nerim.net
> |
> | : requirement that std::aligned_storage<T>::type be a synonymous
> | : for char[sizeof (T)] with the additional attribute that it is suitably
> | : aligned.
> |
> | I personally don't need it to be "synonymous for char[sizeof (T)]"
> | with some magic [w.r.t. conventional chars] "additional attribute
> | that it is suitably aligned".
> |
> | An 'opaque' POD type would be 'sufficient', I think.
>
> Well, "an opaque POD type" is also a magic.
I mean that (for example):
struct Something : virtual AnotherSomething
{ /**/ };
class FancyDouble {
double value;
public:
Double();
Double( const Double& );
Double& operator=(const Double&);
~Double();
};
could then result in (provided/"defined" by the implementation):
union __Something_aligned_storage_pod
{ some_pod __align; char __mass[ sizeof( Something ) ]; };
union __FancyDouble_aligned_storage_pod
{ double __align; };
Uhmm. I don't see any magic attributes here.
> And if all you want is to have a POD type, then you can safely ignore
> about the additional alignment atttibute.
>
> [...]
>
> | http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Alignment.html#Alignment
>
> I'll well aware of this. That might be one of the reason why I'm not
> convinced of the need to introduce a core language extention.
>
> Actually, I'm envisioning support for "alignment" storage in the
> library having two components:
>
> 1) std::aligned_storage<T, N>::type;
Is this an array or what? ;-)
> 2) std::type_traits<T>::alignment.
Yeah, and perhaps:
MT_std::type_traits< void >::memory_granularity.
;-) ;-)
regards,
alexander.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@codesourcery.com>
Date: Mon, 15 Jul 2002 14:45:50 GMT Raw View
terekhov@web.de (Alexander Terekhov) writes:
| > | http://groups.google.com/groups?selm=m3bs9gu4hy.fsf%40merlin.nerim.net
| > |
| > | : requirement that std::aligned_storage<T>::type be a synonymous
| > | : for char[sizeof (T)] with the additional attribute that it is suitably
| > | : aligned.
| > |
| > | I personally don't need it to be "synonymous for char[sizeof (T)]"
| > | with some magic [w.r.t. conventional chars] "additional attribute
| > | that it is suitably aligned".
| > |
| > | An 'opaque' POD type would be 'sufficient', I think.
| >
| > Well, "an opaque POD type" is also a magic.
|
| I mean that (for example):
|
| struct Something : virtual AnotherSomething
| { /**/ };
|
| class FancyDouble {
| double value;
| public:
| Double();
| Double( const Double& );
| Double& operator=(const Double&);
| ~Double();
| };
|
| could then result in (provided/"defined" by the implementation):
|
| union __Something_aligned_storage_pod
| { some_pod __align; char __mass[ sizeof( Something ) ]; };
|
| union __FancyDouble_aligned_storage_pod
| { double __align; };
|
| Uhmm. I don't see any magic attributes here.
The magic lies in the definition by the implementation of
__Something_aligned_storage_pod, its semantics and such. What are the
requirements on __Something_aligned_storage_pod::__mass?
__Something_aligned_storage_pod::__align?
[...]
| > 2) std::type_traits<T>::alignment.
|
| Yeah, and perhaps:
|
| MT_std::type_traits< void >::memory_granularity.
Why not.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: David Schwartz <davids@webmaster.com>
Date: Thu, 11 Jul 2002 03:39:06 CST Raw View
Allan W wrote:
> If you have some way to *know* I'm wrong about this -- not just a
> "could-be" but a "has-to-be", or better yet a real-life example --
> I would love to hear about it.
You are definitely right, as James Dennett pointed out, were you not
right, 'malloc' could not work.
DS
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@merlin.nerim.net>
Date: 12 Jul 2002 02:58:38 GMT Raw View
gneppert@web.de (McNepp) writes:
| Yes, portable support for alignment is long overdue.
| But why not keep it as simple as possible?
| We want this declaration:
|
| char buffer[ count * sizeof(T) ];
|
| to be a suitably aligned buffer for any type T.
| So what is really needed is just a simple specifier (e.g. "max_align")
| that does the trick:
|
| char max_align buffer[ count * sizeof(T) ];
I'm not (yet) convinced that a simple type specifier is necessary: A
library solution may suffice:
std::aligned_storage<T>::type buffer[count]
with the requirement that std::aligned_storage<T>::type be a synonymous
for char[sizeof (T)] with the additional attribute that it is suitably
aligned. No need for extra arithmetic. Robust.
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Baugereau" <baugereau@ifrance.kom>
Date: 12 Jul 2002 16:06:34 GMT Raw View
I quite agree but you often want to specify a different alignment for
different allocations of the same type
std::aligned_storage<T,128>::type buffer[count] might be better (but I guess
we can have a default parameter).
"Gabriel Dos Reis" <gdr@merlin.nerim.net> wrote in message
news:m3bs9gu4hy.fsf@merlin.nerim.net...
>
> gneppert@web.de (McNepp) writes:
>
> | Yes, portable support for alignment is long overdue.
> | But why not keep it as simple as possible?
> | We want this declaration:
> |
> | char buffer[ count * sizeof(T) ];
> |
> | to be a suitably aligned buffer for any type T.
> | So what is really needed is just a simple specifier (e.g. "max_align")
> | that does the trick:
> |
> | char max_align buffer[ count * sizeof(T) ];
>
> I'm not (yet) convinced that a simple type specifier is necessary: A
> library solution may suffice:
>
> std::aligned_storage<T>::type buffer[count]
>
> with the requirement that std::aligned_storage<T>::type be a synonymous
> for char[sizeof (T)] with the additional attribute that it is suitably
> aligned. No need for extra arithmetic. Robust.
>
> --
> Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
>
>
>
> [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
> [ about comp.lang.c++.moderated. First time posters: do this! ]
>
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
>
>
Author: Alexander Terekhov <terekhov@web.de>
Date: Fri, 12 Jul 2002 16:14:29 GMT Raw View
Gabriel Dos Reis wrote:
>
> gneppert@web.de (McNepp) writes:
>
> | Yes, portable support for alignment is long overdue.
> | But why not keep it as simple as possible?
> | We want this declaration:
> |
> | char buffer[ count * sizeof(T) ];
> |
> | to be a suitably aligned buffer for any type T.
> | So what is really needed is just a simple specifier (e.g. "max_align")
> | that does the trick:
> |
> | char max_align buffer[ count * sizeof(T) ];
>
> I'm not (yet) convinced that a simple type specifier is necessary: A
> library solution may suffice:
>
> std::aligned_storage<T>::type buffer[count]
aligned_storage_pod(T) buffer; // implementation-defined POD type
struct something {
union {
aligned_storage_pod(T1) t1_buffer;
aligned_storage_pod(T2) t2_buffer;
};
};
typedef T* pointer;
typedef aligned_storage_pod(T)* storage_pointer;
void construct(pointer p, const T& val);
// Effect: new((void*)p) T(val)
void construct(storage_pointer sp, const T& val);
// Effect: new((void*)sp) T(val)
#include <cstddef>
template <class T> class alignment {
struct mass { char c; aligned_storage_pod(T) t; };
public:
static const std::size_t value = offsetof( mass,t );
};
<?>
regards,
alexander.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gneppert@web.de (McNepp)
Date: Fri, 12 Jul 2002 11:55:05 CST Raw View
Daniel Miller <daniel.miller@tellabs.com> wrote in message news:<3D2B6AFF.8030604@tellabs.com>...
>
> No, McNepp is suggesting that the compiler notice that
>
> void identifier[ integer-expression ];
>
> is a pointer to void much like
>
> void* identifier;
>
> but pointing to an allocation of integer-expression bytes which starts
> at the maximally-sized alignment on that platform. What the compiler
> "notices" is the * versus the [] without automagically diving down into
> the integer-expression as you suggest.
>
> If one wants only maximally-sized alignment, I think that McNepp's
> syntax is interesting.
>
> But on the contrary I would prefer to not simply have only
> maximally-sized alignment though. I would prefer alignment correct for
> T which might be far less than the platform's maximal-alignment.
>
> Basing maximally-sized alignment as McNepp does (or T-sized alignment
> as I would prefer) on currently illegal syntax would not break existing
> code---other than existing C++ parsers :-). Conversely, new keywords
> always break someone's code somewhere.
>
Right! That's exactly why I proposed the "void buffer[ somesize ]"
syntax.
I know that it does not address all alignment issues, but it would
provide the kind of stack-based "malloc" that many C++ programmers
have been missing so far.
> For example one could imagine legalizing currently illegal syntax for
> specifying alignment proper for T (assuming T's alignment needs are less
> than the platform's maximum alignment).
>
> void identifier[ T ]; // T-aligned bytes to hold one T instance
>
Hmm, I must admit that as soon as you try to extend my original
"void[] as-untyped-buffer" idiom further, it starts looking a bit
messy.
I can understand the desire to create properly aligned memory for
specific types, but maybe for that purpose a new keyword (such as a
pseudo-template operator align<T>, as others have suggested) would be
the cleaner solution.
Cheerio,
Gernot
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@merlin.nerim.net>
Date: Fri, 12 Jul 2002 18:36:57 GMT Raw View
Alexander Terekhov <terekhov@web.de> writes:
[...]
| > I'm not (yet) convinced that a simple type specifier is necessary: A
| > library solution may suffice:
| >
| > std::aligned_storage<T>::type buffer[count]
|
| aligned_storage_pod(T) buffer; // implementation-defined POD type
std::aligned_storage<T>::type is such a POD. What else am I missing?
--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: David Schwartz <davids@webmaster.com>
Date: Tue, 9 Jul 2002 16:59:38 GMT Raw View
McNepp wrote:
> Yes, portable support for alignment is long overdue.
> But why not keep it as simple as possible?
> We want this declaration:
>
> char buffer[ count * sizeof(T) ];
>
> to be a suitably aligned buffer for any type T.
> So what is really needed is just a simple specifier (e.g. "max_align")
> that does the trick:
>
> char max_align buffer[ count * sizeof(T) ];
>
> Now we can safely cast this buffer to a T-array, using two
> static_casts...
> which immediately triggers the question: Why not skip the new keyword
> altogether and even get rid of one of the static_casts?
> What about allowing this syntax:
>
> void buffer[ count * sizeof(T) ];
>
> This generic buffer can be safely cast (with one simple static_cast)
> to any type T. No new keywords needed, simple and self-explanatory,
> isn't it?
My problem with your first suggestion is that it's always possible to
have a machine where two different data types have conflicting alignment
requirements such that it's not possible to properly align a buffer for
both of them.
My problem with your second suggestion is that it's not clear to me
what it is exactly that you're suggesting. Are you saying the compiler
should notice the 'sizeof(T)' in there and conclude that you want it
properly aligned? If so, what about:
void buffer[ 3 + count * sizeof(T) ];
or
void buffer[ (count * sizeof(T)) + (count2 * sizeof(T2)) ];
or
void buffer[ sizeof(T) * sizeof(U) ];
If you're suggesting some general mechanism, what's the syntax? Is it
specific to cases where you multiply something other than a 'sizeof' by
a 'sizeof'?
DS
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Dennett <jdennett@acm.org>
Date: Tue, 9 Jul 2002 21:22:28 GMT Raw View
David Schwartz wrote:
> McNepp wrote:
>
>
>>Yes, portable support for alignment is long overdue.
>>But why not keep it as simple as possible?
>>We want this declaration:
>>
>>char buffer[ count * sizeof(T) ];
>>
>>to be a suitably aligned buffer for any type T.
>>So what is really needed is just a simple specifier (e.g. "max_align")
>>that does the trick:
>>
>>char max_align buffer[ count * sizeof(T) ];
>>
>>Now we can safely cast this buffer to a T-array, using two
>>static_casts...
>>which immediately triggers the question: Why not skip the new keyword
>>altogether and even get rid of one of the static_casts?
>>What about allowing this syntax:
>>
>>void buffer[ count * sizeof(T) ];
>>
>>This generic buffer can be safely cast (with one simple static_cast)
>>to any type T. No new keywords needed, simple and self-explanatory,
>>isn't it?
>
>
> My problem with your first suggestion is that it's always possible to
> have a machine where two different data types have conflicting alignment
> requirements such that it's not possible to properly align a buffer for
> both of them.
Such a machine cannot support C or C++ in a natural way,
because malloc is already required to return memory suitably
aligned for use by an arbitrary type. (7.20.3/1 in 9899:1999,
sorry I don't have 9899:1990 to hand.)
3.7.3.1/2 of 14882:1998 says similar things for C++ allocation
functions. 5.3.4/10 has more to say on the subject.
Both C and C++ make assumptions about alignment, including
what amounts to the assumption that the alignment of each
type can be expressed as a simple integral value. Types
with conflicting alignment requirements are not permitted.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Allan_W@my-dejanews.com (Allan W)
Date: Wed, 10 Jul 2002 00:04:20 GMT Raw View
David Schwartz <davids@webmaster.com> wrote
> ...it's always possible to
> have a machine where two different data types have conflicting alignment
> requirements such that it's not possible to properly align a buffer for
> both of them.
I've heard this assertion before, but I don't believe it's true.
If some data type A requires alignment on an M-byte boundary, and
some data type B requires alignment on an N-byte boundary, then
there must be some multiple P=LCM(M,N) which works for both of them.
(LCM=Least Common Multiple).
Or are you saying that some CPU/compiler combination could have some
built-in data type that requires alignment to a multiple of some
constant, PLUS another constant? For instance, some computer
might require 4-byte integers to be aligned at 4N+2:
2, 6, 10, 14, and so on. Is that what you mean? If so, why?!?
Although I can't claim to have seen (or even heard of) every CPU in
the world, I still find it doubtful that such a thing exists.
"But what," you might counter, "about structures?" i.e.
struct baz {
char foo;
long bar;
};
If long requires alignment on a 4N boundary, this does *NOT* mean that
baz requires on a 4N-1 (or equivalently, 4N+3) boundary. Instead, it
means that sizeof(baz)=8 instead of 5. If you think about it, that's
how it has to be -- otherwise there would be no way for this to work:
baz baza[10];
If sizeof(baz) was 5, then even if baza[0] were aligned, baza[1]
would not be. So the size baz has to be a multiple of the most-
critically-aligned element of baz; in this case, baz has to be a
multiple of 8 bytes. There will be 3 padding bytes between foo
and bar.
If you have some way to *know* I'm wrong about this -- not just a
"could-be" but a "has-to-be", or better yet a real-life example --
I would love to hear about it.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Daniel Miller <daniel.miller@tellabs.com>
Date: Wed, 10 Jul 2002 00:06:25 GMT Raw View
David Schwartz wrote:
> McNepp wrote:
[...snip...]
>>which immediately triggers the question: Why not skip the new keyword
>>altogether and even get rid of one of the static_casts?
>>What about allowing this syntax:
>>
>>void buffer[ count * sizeof(T) ];
>>
>>This generic buffer can be safely cast (with one simple static_cast)
>>to any type T. No new keywords needed, simple and self-explanatory,
>>isn't it?
>>
[...snip...]
> My problem with your second suggestion is that it's not clear to me
> what it is exactly that you're suggesting. Are you saying the compiler
> should notice the 'sizeof(T)' in there and conclude that you want it
> properly aligned?
No, McNepp is suggesting that the compiler notice that
void identifier[ integer-expression ];
is a pointer to void much like
void* identifier;
but pointing to an allocation of integer-expression bytes which starts
at the maximally-sized alignment on that platform. What the compiler
"notices" is the * versus the [] without automagically diving down into
the integer-expression as you suggest.
If one wants only maximally-sized alignment, I think that McNepp's
syntax is interesting.
But on the contrary I would prefer to not simply have only
maximally-sized alignment though. I would prefer alignment correct for
T which might be far less than the platform's maximal-alignment.
Basing maximally-sized alignment as McNatt does (or T-sized alignment
as I would prefer) on currently illegal syntax would not break existing
code---other than existing C++ parsers :-). Conversely, new keywords
always break someone's code somewhere.
For example one could imagine legalizing currently illegal syntax for
specifying alignment proper for T (assuming T's alignment needs are less
than the platform's maximum alignment).
void identifier[ T ]; // T-aligned bytes to hold one T instance
void identifier[ T ][ 3 ]; // T-aligned bytes to hold three T
// instances
void identifier[ T* ]; // bytes to hold one pointer to T
// properly aligned for such pointer
void identifier[ T* ][ 5 ]; // bytes to hold five pointers to T
// properly aligned for such pointer
and so forth. Other currently-illegal syntaxes could be devised
instead, as one's artistic/aesthetic taste prefers. My example syntax
would be as though operator[] were
overloaded on T for type/"class" void,
overloaded on T[3] for type/"class" void,
overloaded on T* for type/"class" void,
overloaded on T*[5] for type/"class" void
respectively in my examples above, where void is conceptually the class
of untyped bytes.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: 7 Jun 2002 22:53:45 GMT Raw View
McNepp wrote:
[SNIP]
> heap. This purpose it would serve well enough, and why bother about a
> few wasted bytes if the alternative was highly expensive (and, BTW,
> wasteful, too) malloc/operator new calls?
Probably, because there was a "design rule" or "base statement" for C++,
that the intent is to make no room for anything else than assembly below
it? BTW those few wasted bytes may just mean out-of-luck situ on an
embedded system. Because we do not talk about few wasted bytes, but few
wasted bytes _everywhere_! And what, if the system has some special HW
(like matrix/vector/whatever) with a special floating point[array]
type... and that has to be aligned to 8K page bounday? Will you
actually allocate 3 integers padded up to 8K?
Attila
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gneppert@web.de (McNepp)
Date: 2 Jun 2002 01:12:32 GMT Raw View
"David Abrahams" <david.abrahams@rcn.com> wrote in message news:<ad0l2u$4vn$1@bob.news.rcn.net>...
> "McNepp" <gneppert@web.de> wrote in message
> news:53e3f3b2.0205270557.bdd703d@posting.google.com...
> > What about allowing this syntax:
> >
> > void buffer[ count * sizeof(T) ];
> >
> > This generic buffer can be safely cast (with one simple static_cast)
> > to any type T. No new keywords needed, simple and self-explanatory,
> > isn't it?
>
> ...but very wasteful in generic code where T might turn out to be char.
>
Sure, it may waste a few bytes, but it is supposed to be a simple,
fast, stack-based replacement for dynamic memory allocation on the
heap. This purpose it would serve well enough, and why bother about a
few wasted bytes if the alternative was highly expensive (and, BTW,
wasteful, too) malloc/operator new calls?
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "David Abrahams" <david.abrahams@rcn.com>
Date: 3 Jun 2002 15:06:21 GMT Raw View
"McNepp" <gneppert@web.de> wrote in message
news:53e3f3b2.0205302330.67a3eeb5@posting.google.com...
> Sure, it may waste a few bytes, but it is supposed to be a simple,
> fast, stack-based replacement for dynamic memory allocation on the
> heap. This purpose it would serve well enough, and why bother about a
> few wasted bytes if the alternative was highly expensive (and, BTW,
> wasteful, too) malloc/operator new calls?
If that were the only alternative, I wouldn't bother about it.
However, if you're going to introduce a language extension, there's no sense
crippling it. I wouldn't support any alignment extension which only allowed
us to make storage of maximal alignment, since it would be so easy to have
the extension give us storage appropriately aligned for a particular type.
-Dave
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "David Abrahams" <david.abrahams@rcn.com>
Date: 30 May 2002 16:17:19 GMT Raw View
"McNepp" <gneppert@web.de> wrote in message
news:53e3f3b2.0205270557.bdd703d@posting.google.com...
>
> Attila Feher <Attila.Feher@lmf.ericsson.se> wrote in message
news:<3CEA1A08.C6D95CC7@lmf.ericsson.se>...
> What about allowing this syntax:
>
> void buffer[ count * sizeof(T) ];
>
> This generic buffer can be safely cast (with one simple static_cast)
> to any type T. No new keywords needed, simple and self-explanatory,
> isn't it?
...but very wasteful in generic code where T might turn out to be char.
-Dave
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Daniel Miller <daniel.miller@tellabs.com>
Date: 30 May 2002 16:17:19 GMT Raw View
Attila Feher wrote:
[...snip...]
> Suggestion for new aligment language features for C++
> =====================================================
[...snip...]
> Solution #2:
> ------------
>
> This solution requires a new, special keyword in the declarations,
> hides all the know-how, and therefore a bit more complicated for the
> implementors but much easier for the users. And it is less flexible
> than #1, since with #1 I can even create a T *tp with align, then say
> Y *yp=align<Y>( tp+1); and position a Y after the T in the memory.
>
> This solution would enable the coder to change alignment of any type
On certain processors, certain data-types must be aligned in certain
ways or
else a fault occurs. On such processors where misalignment precipitates
such a
fault, that fault is typically harshly abortive outside of C++'s direct
control/inhibition, such as dumping core memory in UNIX-family operating
systems.
One typically sees such harsh misalignment faulting on processors
outside of
the CISC world. CISC processors typically permit suboptimal alignments
with a
performance penalty. Many RISC & VLIW processors are not so permissive
in an
effort to save on silicon by reducing nonessential features, in that
they
generally require a nonaggregate scalar datum whose sizeof is k bytes to
be
aligned on an address s where s mod k == 0.
> or
> just char arrays in declarations. As it seems it is enough for just
> char arrays, but you may see a good reason for open it up to arrays or
> any other type.
The following could be "opened up" only to a type T where sizeof(T)
is a
multiple of sizeof the type being declared. My example demonstrations
of
troublesome cases follows.
> It could look something like this:
>
> align_as<T> char T_arr[sizeof(T)*S];
For example, if the type being declared were to be a 16-bit short and
T were to be an 8-bit char on a particular platform (whose shorts are
two octets and whose chars are one octet), then use of that datum would
cause degraded performance on certain processors and cause a fault on
other processors for any 16-bit address s where s % sizeof(short) != 0
which would occur for 8-bit-char-based alignments of s % sizeof(16-bit
short) == 1.
Similarly, if the type being declared were to be a 32-bit int and T
were to be an 80-bit double on a particular platform (with such sizes of
scalar datatypes and char is 8-bit), then use of that datum would cause
degraded performance on certain processors and cause a fault on other
processors for any 80-bit address s where s % sizeof(32-bit int) != 0
which would occur for 80-bit-double-based alignments of s, where s is in
the set {10k} where k is an element of the set of nonnegative integers.
> So align_as would be a sort of "storage specifier like thing",
> possibly behaving the same as static from syntax point of view.
> Except that it would not "collide" with any storage specifiers, since
> it is a different
> thing: alignment specifier.
[...snip...]
> Conclusion:
> -----------
>
> I see many people struggling with alignment issues. With the current
> set of language support (nil), we cannot solve this problem portably.
Portable solutions to the alignment-detection problems exist, but can
be
extremely arcane, involving much typecasting & pointer arithmetic to
discover
what this compiler on this platform is doing to the pad-bytes when type
x is
declared after type y. A knowledge-base can be built-up at run-time via
investigation of const char* value of various static or file-scope
data-structures whose fields represent the the combination of types
whose
alignment-pairings are of interest.
Portable solutions to the alignment-imposing problems exist, but can
be
extremely arcane, involving much typecasting, much pointer arithmetic,
and many
invocations of default placement operator new.
What doesn't currently exist within the C++ standard is *simple* and
*direct*
portable solutions to the various alignment-discovery or
alignment-control problems.
> Adding this max_align(), align<T>() and align_as<T> to the language we
> can allow people to save the dynamic memory allocation and still have
> a rather STL like container: but on the stack, which is thread safe,
> not like the heap/free-store.
[...snip...]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Christopher Eltschka <celtschk@web.de>
Date: 30 May 2002 16:17:20 GMT Raw View
Attila Feher <Attila.Feher@lmf.ericsson.se> writes:
[...]
> Solution #1:
> ------------
>
> This solution is more work for the users of the language, the way to
> solve the problem is not so elegant, but it is probably easy to
> implement.
>
> Two additions to the language are required here:
>
> 1.) max_align(T) compile time operator(?)
>
> 2.) T *std::align<T>( void *ptr[, std::size_t size]) runtime function
>
> The max_align<T> works like sizeof. It gives the maximum
> "alignment loss" in bytes one can get with the type T. So if type T
> needs to be aligned on 8 bytes boundary, max_align(T) would give 7,
> because we can loose max. 7 bytes, if we align this type.
>
> The align<T>(ptr[, size]) template like function would give return an
> address _after_ ptr, which is properly aligned for type T. The caller
> can then create a type T at that address using replacement new.
>
> The second overload of align would check if it aligns ptr to a T is
> there any space left in those size bytes to create a T. If not, it
> throws some std::whatever_we_call_it.
>
> The max_align would help in allocation:
>
> template <typename T, std::size_t S>
> class fsdc_array {
>
> T *arr_;
> char buff_[sizeof(T)+max_align(T)];
> };
>
> The align would help in figuring out the address of the first element:
>
> template blabla
> fsdc_array::fsdc_array() {
> arr_ = align<T>( buff_);
> }
>
> The code of the array template could then address its elements via
> arr_.
>
>
> Solution #2:
> ------------
>
> This solution requires a new, special keyword in the declarations,
> hides all the know-how, and therefore a bit more complicated for the
> implementors but much easier for the users. And it is less flexible
> than #1, since with #1 I can even create a T *tp with align, then say
> Y *yp=align<Y>( tp+1); and position a Y after the T in the memory.
>
> This solution would enable the coder to change alignment of any type
> or just char arrays in declarations. As it seems it is enough for
> just char arrays, but you may see a good reason for open it up to
> arrays or any other type.
>
> It could look something like this:
>
> align_as<T> char T_arr[sizeof(T)*S];
>
> So align_as would be a sort of "storage specifier like thing",
> possibly behaving the same as static from syntax point of view.
> Except that it would not "collide" with any storage specifiers, since
> it is a different
> thing: alignment specifier.
>
>
> Solution #3:
> ------------
>
> Provide both #1 and #2, allowing the nice "tricks" described about #1
> under #2 (opening up a great flexibility) as well as give an easy way
> to do the easy thing.
Solution #4:
Provide a built-in "class template" align<T> with the following
properties:
a) align<T> has the samme alignment restrictions as T
b) align<T> has the smallest size compatrible with those alignment
restrictions (i.e. sizeof(align<T>) gives the alignment of T)
c) align<T> is POD
As a special case, make align<void> be suitable allignd for
Now you can get an aligned memory area f.ex. with
union
{
align<int> int_alignment; // forces alignment
unsigned char intarr[100*sizeof(int)]; // aligned for int
};
union
{
align<void> void_alignment;
unsigned char arr[10000]; // aligned for arbitrary type
}
char* p = arr + sizeof(align<double>);
// p is the second position in arr correctly aligned for double
char* q = arr + sizeof(align<void>);
// q is the second position in arr correctly aligned for any type
[...]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: James Kanze <kanze@alex.gabi-soft.de>
Date: 28 May 2002 15:47:44 GMT Raw View
Attila Feher <Attila.Feher@lmf.ericsson.se> writes:
|> Suggestion for new aligment language features for C++
|> =====================================================
|> Dynamic memory allocation is expensive. To pay for it, just to
|> get right alignment is silly.
|> Motivation:
|> -----------
|> C++ programmers many times face the issue of being able to create
|> fixed capacity, dynamic sized sequential containers. Right now,
|> with current language features such a container can only be
|> implemented using dynamic memory allocation, like vector. But in
|> many cases, such an allocation is an overkill.
[...]
|> Solution #2:
|> ------------
|> This solution requires a new, special keyword in the declarations,
|> hides all the know-how, and therefore a bit more complicated for
|> the implementors but much easier for the users. And it is less
|> flexible than #1, since with #1 I can even create a T *tp with
|> align, then say Y *yp=align<Y>( tp+1); and position a Y after the
|> T in the memory.
|> This solution would enable the coder to change alignment of any
|> type or just char arrays in declarations.
Change, or require?
I think that g++ has something similar, as an extension.
|> As it seems it is enough for just char arrays, but you may see a
|> good reason for open it up to arrays or any other type.
It's more a question of there not being any reason to restrict it.
Orthogonality is a virtue.
|> It could look something like this:
|> align_as<T> char T_arr[sizeof(T)*S];
|> So align_as would be a sort of "storage specifier like thing",
|> possibly behaving the same as static from syntax point of view.
|> Except that it would not "collide" with any storage specifiers,
|> since it is a different thing: alignment specifier.
Well, it probably wouldn't be relevant to allow it on a typedef.
The fact that g++ has implemented it as an extension means that 1)
there is obviously some demand for it, and 2) there is some existing
practice.
--
James Kanze mailto:kanze@gabi-soft.de
Need real expertise in C++, Java, OO design
I am available, see my CV at www.gabi-soft.de
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)69 63198627
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: gneppert@web.de (McNepp)
Date: 28 May 2002 15:47:45 GMT Raw View
Attila Feher <Attila.Feher@lmf.ericsson.se> wrote in message news:<3CEA1A08.C6D95CC7@lmf.ericsson.se>...
>
>
> Motto:
> ------
>
> Dynamic memory allocation is expensive. To pay for it, just to get
> right alignment is silly.
>
>
> Motivation:
> -----------
>
> C++ programmers many times face the issue of being able to create fixed
> capacity, dynamic sized sequential containers. Right now, with current
> language features such a container can only be implemented using dynamic
> memory allocation, like vector. But in many cases, such an allocation
> is an overkill.
>
Yes, portable support for alignment is long overdue.
But why not keep it as simple as possible?
We want this declaration:
char buffer[ count * sizeof(T) ];
to be a suitably aligned buffer for any type T.
So what is really needed is just a simple specifier (e.g. "max_align")
that does the trick:
char max_align buffer[ count * sizeof(T) ];
Now we can safely cast this buffer to a T-array, using two
static_casts...
which immediately triggers the question: Why not skip the new keyword
altogether and even get rid of one of the static_casts?
What about allowing this syntax:
void buffer[ count * sizeof(T) ];
This generic buffer can be safely cast (with one simple static_cast)
to any type T. No new keywords needed, simple and self-explanatory,
isn't it?
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: 29 May 2002 02:42:07 GMT Raw View
McNepp wrote:
[SNIP]
> Yes, portable support for alignment is long overdue.
> But why not keep it as simple as possible?
I guess what I have suggested is simple.
> We want this declaration:
>
> char buffer[ count * sizeof(T) ];
>
> to be a suitably aligned buffer for any type T.
Nope. I wan't it to be suitably aligned to the _specific_ type T used
there! Not _any_, because this means wasting of memory!
> So what is really needed is just a simple specifier (e.g. "max_align")
> that does the trick:
>
> char max_align buffer[ count * sizeof(T) ];
One point of my proposal was to avoid using maximum alignment
everywhere.
> Now we can safely cast this buffer to a T-array, using two
> static_casts... which immediately triggers the question: Why not skip
> the new keyword altogether and even get rid of one of the
> static_casts? What about allowing this syntax:
>
> void buffer[ count * sizeof(T) ];
>
> This generic buffer can be safely cast (with one simple static_cast)
> to any type T. No new keywords needed, simple and self-explanatory,
> isn't it?
It is simple, but it isn't obvious (self explanatory) at all. And what
if I have already (for some reason) the size given to me? So the type T
will not even be mentioned in this line, unless there is a separate
aligment specification?
Also your proposal does not support if I need to align any arbitrary
pointer. Like I have a buffer in shared memory and I would like to
place there an object, which needs alignment. I have a pointer to the
first free byte.
So I guess why being simple is A OK with me, being ambiguously implicit
ends up being "too simple". I believe that this aligment issue needs
two kind of support: an alignment specifier and an "aligment calculator"
taking a void * plus a length and returning void * to the first suitable
address, where type T can be constructed _or_ throws std::ollala if it
cannot be done within the given buffer size. Or you can give "one past
end iterator" as well (instead of length), I guess it even would be
better.
When I say we need these two I mean that we need if we want to have a
complete solution and forget about the problem. And of course: we might
need to allow user defined extension (that's the reason why for the
template syntax) of these two functions (well, I have no idea how could
we actually do sth for the aligment specifier part) so that people can
create their own special aligment requirements for their own special
types. But I guess once we enter this zone, the implementation will
_always_ be platform specific, so we can leave it out as well - since
the whole idea was to remain platform independent. And whoever needs
any more wonders can just use the platform specific address arithmetics
to create a good enough pointer. Since these special cases of more
strict aligment requirements (I guess) can only come up if some special
HW requires it in low level code.
Attila
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: 29 May 2002 02:42:08 GMT Raw View
James Kanze wrote:
[SNIP]
> |> This solution would enable the coder to change alignment of any
> |> type or just char arrays in declarations.
>
> Change, or require?
Yes. :-)))) Change from char alignment requirements to the requirements
of a given type T _or_ require the aligment to be one suitable for the
given type T. I believe this two means the same. We are into
linguistics again! :-)))
> I think that g++ has something similar, as an extension.
It does.
> |> As it seems it is enough for just char arrays, but you may see a
> |> good reason for open it up to arrays or any other type.
>
> It's more a question of there not being any reason to restrict it.
Well, I doubt you would want to align and std::string as long double...
So _if_ it does not make sense, it makes sense to forbid it - since
human errors can be caught this way. The alignment specification (up to
my knowledge) has one use: to create a buffer suitable for a given type
T. Now I believe it is unlikely that anyone would like to build such a
buffer on top of any other type than char or maybe unsigned/signed char.
Since the size of the other built in types is implementation defined and
user defined types (the ones with a non-trivial constructor) are usually
not the best candidates for overwriting...
> Orthogonality is a virtue.
I still would like to see any case when it makes any sense.
> |> It could look something like this:
>
> |> align_as<T> char T_arr[sizeof(T)*S];
>
> |> So align_as would be a sort of "storage specifier like thing",
> |> possibly behaving the same as static from syntax point of view.
> |> Except that it would not "collide" with any storage specifiers,
> |> since it is a different thing: alignment specifier.
> Well, it probably wouldn't be relevant to allow it on a typedef.
AFAIK static cannot be used in a typedef. Whether an alignment
specifier should be is a good question. Probably it would make sense to
be able to define a type alias called bufferForMyTypeBla but in real
life I guess that such a type - or at least its aligment restricted form
- would only be used once. Either once at all or once inside a template
class as a member. So I do not see why would anyone want to create a
typedef of it. Also, to allow it to get into a typedef it should be
part of the type! Which is just plain wrong - I believe - since there
is absolutely no difference in type between a bunch of characters
forcedly aligned on some boundary (if used as characters) and another
bunch of them which are not aligned _or_ happen to be aligned by
accident. Of course, I am open for any concrete example where having
alignment requirements "burnt" into a typedef would be useful or
mandatory to achieve something in a real life scenario.
> The fact that g++ has implemented it as an extension means that 1)
> there is obviously some demand for it, and 2) there is some existing
> practice.
Yep. And looking into the compiler generated code (asm) (on SUN, etc.),
it is also obvious that the compilers actually alreday do the "rain
dance of alignment on the stack", so basically everything is there (at
compile and runtime as well!) in every compiler (for a platform with
alignment requirements) to do this. At least I believe so.
Attila
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Attila Feher <Attila.Feher@lmf.ericsson.se>
Date: 24 May 2002 23:08:50 GMT Raw View
Cross posted to comp.lang.c++.moderated, because I hope that there will
be a fruitful discussion about how to do this best. This is my
proposal, which may serve as a starting point for the discussion.
Please let me know what do you think about it!
Suggestion for new aligment language features for C++
=====================================================
Motto:
------
Dynamic memory allocation is expensive. To pay for it, just to get
right alignment is silly.
Motivation:
-----------
C++ programmers many times face the issue of being able to create fixed
capacity, dynamic sized sequential containers. Right now, with current
language features such a container can only be implemented using dynamic
memory allocation, like vector. But in many cases, such an allocation
is an overkill.
Boost provides an array template, but that is mostly suitable for
free-to-construct or cheap-to-construct elements, since it is a fixed
size (and capacity) container. Therefore users of it pay for default
construction of all elements of the array, or (in case of curly
initialization) default construction of the unused elements. In
addition to that the unused elements will be (unneededly) destroyed as
well. Boost array is very good for built-in types, but shows its
weaknesses (it is an aggregate) when non-C types are involved.
Solution #1:
------------
This solution is more work for the users of the language, the way to
solve the problem is not so elegant, but it is probably easy to
implement.
Two additions to the language are required here:
1.) max_align(T) compile time operator(?)
2.) T *std::align<T>( void *ptr[, std::size_t size]) runtime function
The max_align<T> works like sizeof. It gives the maximum
"alignment loss" in bytes one can get with the type T. So if type T
needs to be aligned on 8 bytes boundary, max_align(T) would give 7,
because we can loose max. 7 bytes, if we align this type.
The align<T>(ptr[, size]) template like function would give return an
address _after_ ptr, which is properly aligned for type T. The caller
can then create a type T at that address using replacement new.
The second overload of align would check if it aligns ptr to a T is
there any space left in those size bytes to create a T. If not, it
throws some std::whatever_we_call_it.
The max_align would help in allocation:
template <typename T, std::size_t S>
class fsdc_array {
T *arr_;
char buff_[sizeof(T)+max_align(T)];
};
The align would help in figuring out the address of the first element:
template blabla
fsdc_array::fsdc_array() {
arr_ = align<T>( buff_);
}
The code of the array template could then address its elements via arr_.
Solution #2:
------------
This solution requires a new, special keyword in the declarations, hides
all the know-how, and therefore a bit more complicated for the
implementors but much easier for the users. And it is less flexible
than #1, since with #1 I can even create a T *tp with align, then say Y
*yp=align<Y>( tp+1); and position a Y after the T in the memory.
This solution would enable the coder to change alignment of any type or
just char arrays in declarations. As it seems it is enough for just
char arrays, but you may see a good reason for open it up to arrays or
any other type.
It could look something like this:
align_as<T> char T_arr[sizeof(T)*S];
So align_as would be a sort of "storage specifier like thing", possibly
behaving the same as static from syntax point of view. Except that it
would not "collide" with any storage specifiers, since it is a different
thing: alignment specifier.
Solution #3:
------------
Provide both #1 and #2, allowing the nice "tricks" described about #1
under #2 (opening up a great flexibility) as well as give an easy way to
do the easy thing.
Conclusion:
-----------
I see many people struggling with alignment issues. With the current
set of language support (nil), we cannot solve this problem portably.
Adding this max_align(), align<T>() and align_as<T> to the language we
can allow people to save the dynamic memory allocation and still have a
rather STL like container: but on the stack, which is thread safe, not
like the heap/free-store.
I know, that the idea of such a container can be attacked from exception
safety point of view. Well, this is the price to pay, if the stored
items are non-PIMPL. If they are, the dsfc array is a great thing: it
is exception safe (swapping, assigning pointers is safe) but saves the
unneeded "malloc call".
------------------------------------------------------------------------
This is posted to both clc++m and cstdc++
Please comment!
MHC:
----
I guess the "support" for all 3 "things" I have suggested is already
present in the language. It may happen that wording these into the
standard may actually take more time then implementing them. There will
be much more questions to answer then I have tried here:
Like should T be a fully defined type? I remember Scott did complain
something about being able to do a vector of incomplete types. Well,
since here we use the size and alignment requirements for the type: I
guess it should be fully defined.
Attila
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]