Topic: Minimum Size of Array in Standard (solution)
Author: ncm@nospam.cantrip.org (Nathan Myers)
Date: 1998/11/12 Raw View
Hans Olsson<Email_To::.Hans.Olsson@dna.lth.se> wrote:
>Nathan Myers <ncm@nospam.cantrip.org> wrote:
>>Hans Olsson<Email_To::.Hans.Olsson@dna.lth.se> wrote:
>>>Nathan Myers <ncm@nospam.cantrip.org> wrote:
>>>>There is a standard-conforming way to get a similar effect.
>>>>
>>>> template <class T>
>>>> struct varstruct
>>>> {
>>>> union {
>>>> unsigned int num_elements;
>>>> T dummy[(sizeof(unsigned int)+sizeof(T)-1)/sizeof(T)];
>>>> };
>>>> T* elements() { return (T*)(char*)(this+1); }
>>>> };
>>>>
>>>>The dummy array ensures that (this+1) is aligned properly for a T.
>>>
>>> why not plain T dummy ?
>>
>>Because a single T might not be big enough.
>
>I understand that T might be smaller than unsigned int, but
>I fail to see the problem.
>
>A union cannot contain padding before its members (can it? would it
>matter?). Since (this+1) is suitably aligned for an object of the
>union (or arrays of unions wouldn't work) it must thus also be suitably
>aligned for an object of type T.
Maybe Hans is right. I think a union cannot contain padding before
its first member, at least. Then this
>>>> union {
>>>> T dummy;
>>>> unsigned int num_elements;
>>>> };
would be sufficient.
>>>Why not have a template-union instead of hiding the union inside
>>>a struct?
>>
>>The point is that the varstruct probably has useful things in it.
>
>But I though those other items should also be inside the union
>(preferably in a struct):
>
>struct header {...}
>template <class T> union varunion {
> struct header;
> T dummy;
> T* elements() {return (T*)(char*)(this+1);}
>};
>varunion<T>* x =
> (varunion<T>*) operator new(sizeof(varunion<T>)+sizeof(T)*n);
This is close to what I meant. That a single T is enough is
a useful insight.
--
Nathan Myers
ncm@nospam.cantrip.org http://www.cantrip.org/
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/11/13 Raw View
In article <72e9ql$mgp$1@shell7.ba.best.com>,
Nathan Myers <ncm@nospam.cantrip.org> wrote:
>[Deleted] I think a union cannot contain padding before
>its first member, at least.
Looking back and forth in CD2 (9.5/1, 9.2/17, 5.9/2) I found that a union
with a POD member cannot contain padding before its members.
Since we assume that T is a POD-type there will not be any padding
in this case (assuming there were no substantial changes in this area
between CD2 and the standard)
I'm not sure about unions without POD-members, but I fail to see the
need for any padding, especially since all members must have the
same adress (5.9/2).
--
// Home page http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/11/12 Raw View
In article <72ak12$ma2$1@shell7.ba.best.com>,
Nathan Myers <ncm@nospam.cantrip.org> wrote:
>
>Hans Olsson<Email_To::.Hans.Olsson@dna.lth.se> wrote:
>>Nathan Myers <ncm@nospam.cantrip.org> wrote:
>>>There is a standard-conforming way to get a similar effect.
>>>
>>> template <class T>
>>> struct varstruct
>>> {
>>> union {
>>> unsigned int num_elements;
>>> T dummy[(sizeof(unsigned int)+sizeof(T)-1)/sizeof(T)];
>>> };
>>> T* elements() { return (T*)(char*)(this+1); }
>>> };
>>>
>>>The dummy array ensures that (this+1) is aligned properly for a T.
>>
>> why not plain T dummy ?
>
>Because a single T might not be big enough.
I understand that T might be smaller than unsigned int, but
I fail to see the problem.
A union cannot contain padding before its members (can it? would it matter?).
Since (this+1) is suitably aligned for an object of the union
(or arrays of unions wouldn't work) it must thus also be suitably
aligned for an object of type T.
>>Why not have a template-union instead of hiding the union inside
>>a struct?
>
>The point is that the varstruct probably has useful things in it.
But I though those other items should also be inside the union
(preferably in a struct):
struct header {...}
template <class T> union varunion {
struct header;
T dummy;
T* elements() {return (T*)(char*)(this+1);}
};
varunion<T>*x=(varunion<T>*)operator new(sizeof(varunion<T>)+sizeof(T)*n);
What non-static data members besides the union could there be in the
varstruct? Static data members are, however, a valid point (although
I fail to see the need for them).
If you meant a varstruct with a pointer to the union, and completely
hide the union from the user of the class I agree
that this is the preferred way.
--
// Home page http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Email_To::.Hans.Olsson@dna.lth.se (Hans Olsson)
Date: 1998/11/10 Raw View
In article <71p6m5$4m1$1@shell7.ba.best.com>,
Nathan Myers <ncm@nospam.cantrip.org> wrote:
>There is a standard-conforming way to get a similar effect.
>
> template <class T>
> struct varstruct
> {
> union {
> unsigned int num_elements;
> T dummy[(sizeof(unsigned int)+sizeof(T)-1)/sizeof(T)];
> };
> T* elements() { return (T*)(char*)(this+1); }
> };
>
>The dummy array ensures that (this+1) is aligned properly for a T.
Apart from the other questions (i.e. why not plain T dummy;):
Why not have a template-union instead of hiding the union inside
a struct?
--
// Home page http://www.dna.lth.se/home/Hans_Olsson/
// Email To..Hans.Olsson@dna.lth.se [Please no junk e-mail]
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ncm@nospam.cantrip.org (Nathan Myers)
Date: 1998/11/11 Raw View
Hans Olsson<Email_To::.Hans.Olsson@dna.lth.se> wrote:
>Nathan Myers <ncm@nospam.cantrip.org> wrote:
>>There is a standard-conforming way to get a similar effect.
>>
>> template <class T>
>> struct varstruct
>> {
>> union {
>> unsigned int num_elements;
>> T dummy[(sizeof(unsigned int)+sizeof(T)-1)/sizeof(T)];
>> };
>> T* elements() { return (T*)(char*)(this+1); }
>> };
>>
>>The dummy array ensures that (this+1) is aligned properly for a T.
>
> why not plain T dummy ?
Because a single T might not be big enough.
>Why not have a template-union instead of hiding the union inside
>a struct?
The point is that the varstruct probably has useful things in it.
Generally it has more than just an unsigned. Template tricks can
be used to make this technique prettier, but [I hope] you don't
use it often enough to make that important.
Note that the above is only appropriate if T is a POD.
--
Nathan Myers
ncm@nospam.cantrip.org http://www.cantrip.org/
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/11/07 Raw View
> > >> "Jim Cobban" <Jim.Cobban.jcobban@nt.com> writes:
> > >> |> struct varstruct
> > >> |> {
> > >> |> unsigned int num_elements;
> > >> |> int elements[0];
> > >> |> };
> > >>
> > >> This code is illegal (in C).
> In article <71p6m5$4m1$1@shell7.ba.best.com>,
> ncm@nospam.cantrip.org (Nathan Myers) wrote:
> > template <class T>
> > struct varstruct
> > {
> > union {
> > unsigned int num_elements;
> > T dummy[(sizeof(unsigned int)+sizeof(T)-1)/sizeof(T)];
> > };
> > T* elements() { return (T*)(char*)(this+1); }
> > };
In article <71sq58$sg8$1@nnrp1.dejanews.com>,
jkanze@otelo.ibmmail.com wrote:
> Of course, while fine for string, you will need to use something else in
> the union for the more general case, where T might have a constructor.
If T might have a constructor or destructor, then the compiler MUST
know how many elements are *Really* in the array. This technique,
and anything similar, simply isn't appropriate in this case. Instead,
use
template<class T>struct varstruct {
unsigned int num_elements;
T *elements;
varstruct(int i)
: num_elements(i)
, elements(new T[i])
{ }
~varstruct() { delete elements; }
};
There may have to be minor code changes, especially if the
first version was used as an I/O buffer. But these changes
should not be radical. Hopefully the I/O routines are
segregated anyway, which means minor changes in very few
places.
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: ncm@nospam.cantrip.org (Nathan Myers)
Date: 1998/11/05 Raw View
>> "Jim Cobban" <Jim.Cobban.jcobban@nt.com> writes:
>> ...
>> |> This is used in a lot of existing code to
>> |> represent an array whose size is known by some implementation specific
>> |> method, for example in a structure such as the following:
>> |>
>> |> struct varstruct
>> |> {
>> |> unsigned int num_elements;
>> |> int elements[0];
>> |> };
>>
>> This code is illegal (in C).
There is a standard-conforming way to get a similar effect.
template <class T>
struct varstruct
{
union {
unsigned int num_elements;
T dummy[(sizeof(unsigned int)+sizeof(T)-1)/sizeof(T)];
};
T* elements() { return (T*)(char*)(this+1); }
};
The dummy array ensures that (this+1) is aligned properly for a T.
If you have more data members than just num_elements, you can put
them in a struct and use that in the sizeof expression in place of
unsigned int.
Of course you have to make sure there is usable storage at this[1].
--
Nathan Myers
ncm@nospam.cantrip.org http://www.cantrip.org/
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Bill Wade" <bill.wade@stoner.com>
Date: 1998/11/05 Raw View
Nathan Myers wrote in message <71p6m5$4m1$1@shell7.ba.best.com>...
> template <class T>
> struct varstruct
> {
> union {
> unsigned int num_elements;
> T dummy[(sizeof(unsigned int)+sizeof(T)-1)/sizeof(T)];
> };
> T* elements() { return (T*)(char*)(this+1); }
> };
>
>The dummy array ensures that (this+1) is aligned properly for a T.
I'm probably missing something simple, but why not just
T dummy[1];
in the union? The class still needs to be properly aligned for T.
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jkanze@otelo.ibmmail.com
Date: 1998/11/05 Raw View
In article <71p6m5$4m1$1@shell7.ba.best.com>,
ncm@nospam.cantrip.org (Nathan Myers) wrote:
> >> "Jim Cobban" <Jim.Cobban.jcobban@nt.com> writes:
> >> ...
> >> |> This is used in a lot of existing code to
> >> |> represent an array whose size is known by some implementation specific
> >> |> method, for example in a structure such as the following:
> >> |>
> >> |> struct varstruct
> >> |> {
> >> |> unsigned int num_elements;
> >> |> int elements[0];
> >> |> };
> >>
> >> This code is illegal (in C).
>
> There is a standard-conforming way to get a similar effect.
>
> template <class T>
> struct varstruct
> {
> union {
> unsigned int num_elements;
> T dummy[(sizeof(unsigned int)+sizeof(T)-1)/sizeof(T)];
> };
> T* elements() { return (T*)(char*)(this+1); }
> };
>
> The dummy array ensures that (this+1) is aligned properly for a T.
> If you have more data members than just num_elements, you can put
> them in a struct and use that in the sizeof expression in place of
> unsigned int.
>
> Of course you have to make sure there is usable storage at this[1].
I believe I posted something along these lines many years back; I actually
use this in the implementation of my string class.
Of course, while fine for string, you will need to use something else in
the union for the more general case, where T might have a constructor.
(I declare a union of all of the built in types, plus a few pointers, under
the name GB_MaxAlign, in a global header file. It's not guaranteed by the
standard, but I really cannot imagine an implementation where some derived
type had stricter alignment requirements than any of the builtin types.)
--
James Kanze email: kanze@gabi-soft.fr
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Larry Brasfield <larry_br@sea_net.com>
Date: 1998/11/05 Raw View
Bill Wade wrote or quoted in message <71sjsf$mi7$1@uuneo.neosoft.com>...
>
>Nathan Myers wrote in message <71p6m5$4m1$1@shell7.ba.best.com>...
>
>> template <class T>
>> struct varstruct
>> {
>> union {
>> unsigned int num_elements;
>> T dummy[(sizeof(unsigned int)+sizeof(T)-1)/sizeof(T)];
>> };
>> T* elements() { return (T*)(char*)(this+1); }
>> };
>>
>>The dummy array ensures that (this+1) is aligned properly for a T.
I confess, my head still hurts after studying that
dimension expression. I just don't see how it
does any good for dummy to have more than 1
element. I also cannot see why dummy[] needs
to be an array at all, but at least that's harmless.
Nor do I see what good the intermediate cast
to char * does. If the concern is that somebody
(with perverse tendencies) might derive T from
varstruct<??>, either that is not possible or the
classes will be unrelated. At any rate, it would
be better to write:
T* elements() { return reinterpret_cast<T*>(this+1); }
I would be tempted to also add:
const T* elements() const ...
>I'm probably missing something simple, but why not just
> T dummy[1];
>in the union? The class still needs to be properly aligned for T.
Why not just
T dummy;
?
--Larry Brasfield
Above opinions may be mine alone.
X-Replace-Address
(Humans may reply at unundered larry_br@sea_net.com )
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]