using a union in an initialization list

B

Bit Byter

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);}
 
B

Bit Byter

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;
 
M

Maxim Yegorushkin

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.
 
D

diamondback

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.
 
E

Erik Wikström

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;
}
 
J

James Kanze

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 ;
};

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.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top