[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

using a union in an initialization list

Bit Byter

10/3/2008 12:38:00 PM

I just realized that I cant use a union in an initialization list (or
at least not the way I tried to use it).

This is what I did:

class ValueObject
{
public:
ValueObject();
ValueObject(const ValueObject&);
ValueObject& operatr= (const ValueObject&);

private:
union Item { int i, double d, char s[8]} m_item ;
enum { integer, Double, String } m_type ;
};


//impl:

ValueObject():m_type(Integer), m_item.i(0) //<- compiler complains
{}

ValueObject():m_type(Integer)//<- compiler ok with this - why?
{m_item.i(0);}

5 Answers

Bit Byter

10/3/2008 12:41:00 PM

0

On Oct 3, 1:38 pm, Bit Byter <takashi_...@hotmail.com> wrote:
> I just realized that I cant use a union in an initialization list (or
> at least not the way I tried to use it).
>
> This is what I did:
>
> class ValueObject
> {
> public:
> ValueObject();
> ValueObject(const ValueObject&);
> ValueObject& operatr= (const ValueObject&);
>
> private:
> union Item { int i, double d, char s[8]} m_item ;
> enum { integer, Double, String } m_type ;
>
> };
>
> //impl:
>
> ValueObject():m_type(Integer), m_item.i(0) //<- compiler complains
> {}
>
> ValueObject():m_type(Integer)//<- compiler ok with this - why?
> {m_item.i(0);}


//Corrections:
1. assignment operator misspelled should be 'operator='
2. ctor statement should read: m_item.i = 0;

Maxim Yegorushkin

10/3/2008 2:07:00 PM

0

On Oct 3, 1:38 pm, Bit Byter <takashi_...@hotmail.com> wrote:
> I just realized that I cant use a union in an initialization list (or
> at least not the way I tried to use it).
>
> This is what I did:
>
> class ValueObject
> {
> public:
>      ValueObject();
>      ValueObject(const ValueObject&);
>      ValueObject& operatr= (const ValueObject&);
>
> private:
>    union Item { int i, double d,  char s[8]} m_item ;
>   enum { integer, Double, String } m_type ;
>
> };
>
> //impl:
>
> ValueObject():m_type(Integer), m_item.i(0) //<- compiler complains
> {}

In the initialiser list you initialise members, not members of
members. This syntax in not valid C++, thus the compiler yields an
error.

In this case your member is a union. The only thing you can do with a
union member in the initialiser list it to default-initialise it. The
default initialisation for a union is zero-initialisation:

ValueObject()
: m_item() // <--- default-initialise
, m_type(Integer)
{}

The other thing is that the original order of your initialisation list
is different from the order of declaration of the member variables.
However, the members mentioned in the initialiser list are still
initialised in the order of declaration. To avoid confusion it is good
practise to have these orders the same.

> ValueObject():m_type(Integer)//<- compiler ok with this - why?

Because in this case there is nothing wrong.

> {m_item.i(0);}

Should be m_item.i = 0 as you mentioned in another post.

--
Max

diamondback

10/3/2008 2:45:00 PM

0

On Oct 3, 5:38 am, Bit Byter <takashi_...@hotmail.com> wrote:
> I just realized that I cant use a union in an initialization list (or
> at least not the way I tried to use it).
>
> This is what I did:
>
> class ValueObject
> {
> public:
>      ValueObject();
>      ValueObject(const ValueObject&);
>      ValueObject& operatr= (const ValueObject&);
>
> private:
>    union Item { int i, double d,  char s[8]} m_item ;
>   enum { integer, Double, String } m_type ;
>
> };
>
> //impl:
>
> ValueObject():m_type(Integer), m_item.i(0) //<- compiler complains
> {}
>
> ValueObject():m_type(Integer)//<- compiler ok with this - why?
> {m_item.i(0);}

Bit,

I am not 100% sure on this one but I'll give it a shot.
The difference between a member initialization list and assignments
made in the constructor body is subtle but relevant. The items in the
initialization list are constructed once. The items NOT in the
initialization list are DEFAULT constructed then COPY constructed when
assigned in the constructor body.

Now enter Unions. A union is a struct with all of it's members
assigned to the same memory location. Disclaimer: what follows is
simply an educated guess on my part. I assume that union members are
constructed using a placement-new type process, so all the members are
declared starting in the same spot in memory. That means that they are
probably constructed in the order that they are declared (ex. i, d,
s, ...). So, after initializing m_item.i, the memory can be, depending
on the implementation, re-initialized by the successive constructors.
This would preclude initializing union members in an initialization
list. All of the union members must be constructed before being
assigned to, so the compiler does not support it.

Hopefully someone who has more knowledge of the C++ standard and
unions can give a more definitive response and tell me if I am full of
it.

Erik Wikström

10/3/2008 4:26:00 PM

0

On 2008-10-03 16:44, diamondback wrote:
> On Oct 3, 5:38 am, Bit Byter <takashi_...@hotmail.com> wrote:
>> I just realized that I cant use a union in an initialization list (or
>> at least not the way I tried to use it).
>>
>> This is what I did:
>>
>> class ValueObject
>> {
>> public:
>> ValueObject();
>> ValueObject(const ValueObject&);
>> ValueObject& operatr= (const ValueObject&);
>>
>> private:
>> union Item { int i, double d, char s[8]} m_item ;
>> enum { integer, Double, String } m_type ;
>>
>> };
>>
>> //impl:
>>
>> ValueObject():m_type(Integer), m_item.i(0) //<- compiler complains
>> {}
>>
>> ValueObject():m_type(Integer)//<- compiler ok with this - why?
>> {m_item.i(0);}
>
> Bit,
>
> I am not 100% sure on this one but I'll give it a shot.
> The difference between a member initialization list and assignments
> made in the constructor body is subtle but relevant. The items in the
> initialization list are constructed once. The items NOT in the
> initialization list are DEFAULT constructed then COPY constructed when
> assigned in the constructor body.
>
> Now enter Unions. A union is a struct with all of it's members
> assigned to the same memory location. Disclaimer: what follows is
> simply an educated guess on my part. I assume that union members are
> constructed using a placement-new type process, so all the members are
> declared starting in the same spot in memory. That means that they are
> probably constructed in the order that they are declared (ex. i, d,
> s, ...). So, after initializing m_item.i, the memory can be, depending
> on the implementation, re-initialized by the successive constructors.
> This would preclude initializing union members in an initialization
> list. All of the union members must be constructed before being
> assigned to, so the compiler does not support it.

Actually union members are not allowed to have non-trivial constructors
(which, I believe, limits the members to built-in types and PODs
containing built-in types). So the member are not, in practice,
initialised at all.

If you want to initialise members of a union you can add a constructor
to the union, which you can then use in the initialisation list:

union Foo
{
int i;
double d;
Foo(double v) : d(v) { }
};

class Bar
{
Foo f;
int i;

public:
Bar(int i, double d) : i(i), f(d) { }
};

int main()
{
Bar b(1, 4.5);
return 0;
}

--
Erik Wikström

James Kanze

10/4/2008 8:25:00 AM

0

On Oct 3, 2:38 pm, Bit Byter <takashi_...@hotmail.com> wrote:
> I just realized that I cant use a union in an initialization
> list (or at least not the way I tried to use it).

> This is what I did:

> class ValueObject
> {
> public:
> ValueObject();
> ValueObject(const ValueObject&);
> ValueObject& operatr= (const ValueObject&);

> private:
> union Item { int i, double d, char s[8]} m_item ;
> enum { integer, Double, String } m_type ;
> };

> //impl:

> ValueObject():m_type(Integer), m_item.i(0) //<- compiler complains
> {}

That's because the syntax doesn't allow it. I suppose it could,
in the case where the element was an agglomerate with a trivial
constructor, but the language standard doesn't provide for it.

> ValueObject():m_type(Integer)//<- compiler ok with this - why?
> {m_item.i(0);}

The line in your constructor body is legal? I should only be
legal if m_item.i were a function. In the constructor body, you
have to use assignment.

There are two possible solutions. The simplest is just use
assignment. All union members are required to have trivial
constructors, so there is no difference between initialization
and assignment. Otherwise, you can provide the union with a
constructor, e.g.:

union Item
{
int i ;
double d ;
char s[ 8 ] ;
Item( int i ) : i( i ) {}
Item( double d ) : d( d ) {}
// ...
} ;

Or unless there are literally millions of these objects, just
use a struct. (That's what I did in a similar case.)

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34