StephenD
StephenD

Reputation: 259

Problems with nested struct constructor and Union

I have a struct nested winin a class and a union of that struct. If I have a struct constructor that takes arguments, then the union won't compile.

I also want to create an instance of the struct using an argument. That line also fails.

class test
{
public:
test(void);
~test(void);

struct dtType {
    // inline constructors with initialisation lists
    dtType() : mins(0), hrs(0),day(0),mnth(0),year(0),DPOffset(0),DTType(0) {}
    dtType(byte z) : mins(z), hrs(z),day(z),mnth(z),year(z),DPOffset(0),DTType(0) {}
    dtType(byte n,byte h, byte d, byte m, byte y, byte o, byte t) : mins(n), hrs(h),day(d),mnth(m),year(y),DPOffset(o),DTType(t) {}

    // overloaded operator functions
    bool operator< (dtType date){return true;};
    bool operator<= (dtType date){return true;};
    bool operator> (dtType date){return true;};
    bool operator>= (dtType date){return true;};
    bool operator== (dtType date){return true;};

    // data members
    unsigned mins: 3;
    unsigned hrs: 5; // 8 bits
    unsigned day: 5; 
    unsigned mnth: 4;
    unsigned year: 7; // 16 bits
    unsigned DPOffset: 6; 
    unsigned DTType  : 2;
};

// if I comment out the union it compiles, otherwise I get:
// error C2620: member 'test::dtUnion::dt' of union 'test::dtUnion' has user-defined  constructor or non-trivial default constructor

union dtUnion { 
    dtType dt;
    unsigned long dtLong; // 32 bits
} dtU;

// if I call dtType judgement_day(); it compiles. Otherwise I get:
dtType judgement_day(1); // error C2059: syntax error : 'constant'

};

Following the answers below I have now tried the following, but I get error C2438: judgement_day,dateMask,timeMask : cannot initialize static class data via constructor

class test
{
public:
    test(): judgement_day(1),dateMask(1,1,1,1,1,0,0),timeMask(1,1,0,0,0,0,0){}
~test();
public:
struct dtType {
    // inline constructors with initialisation lists
    dtType() : mins(0), hrs(0),day(0),mnth(0),year(0),DPOffset(0),DTType(0) {}
    dtType(byte z) : mins(z), hrs(z),day(z),mnth(z),year(z),DPOffset(0),DTType(0) {}
    dtType(byte n,byte h, byte d, byte m, byte y, byte o, byte t) : mins(n), hrs(h),day(d),mnth(m),year(y),DPOffset(o),DTType(t) {}
    // overloaded operator functions
    bool operator< (dtType date){return true;};
    bool operator<= (dtType date){return true;};
    bool operator> (dtType date){return true;};
    bool operator>= (dtType date){return true;};
    bool operator== (dtType date){return true;};
    // data members
    unsigned mins: 3;
    unsigned hrs: 5; // 8 bits
    unsigned day: 5; 
    unsigned mnth: 4;
    unsigned year: 7; // 16 bits
    unsigned DPOffset: 6; 
    unsigned DTType  : 2;
};
const static dtType judgement_day;
const static dtType dateMask;
const static dtType timeMask;
};

Upvotes: 1

Views: 1390

Answers (4)

Mike Seymour
Mike Seymour

Reputation: 254431

Others have answered the question about the union; it can't contain members with non-trivial default constructors. To answer the second question, about member initialisation:

You can't initialise non-static members in the class definition; they have to be initialised in the constructor's initialiser list:

class test {
    // stuff
    dtType judgement_day;
};

test::test() : judgement_day(1) {}

The reason that dtType judgement_day(); compiles is that it's declaring a function, not a variable.

UPDATE: since you actually want these members to be static, they are instead initialised in a source file, similarly to global variables:

// in the header
class test {
    // stuff
    const static dtType judgement_day;
};

// in exactly one source file
const test::dtType dtType::judgement_day(1);

Upvotes: 1

acraig5075
acraig5075

Reputation: 10756

For as long as the union contains a dtType member, then dtType cannot have constructors.

However you can change your contructors to be void Set() functions instead, to be called implicitly after a construction.

For example:

int main()
{
    test::dtType judgement_day;
    judgement_day.Set(1);

    test::dtUnion x;
    x.dt.Set(1);

    assert(judgement_day == x.dt);
    return 0;
}

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409166

A union can not contain class instances. Consider a union containing two objects, when creating that union which constructor should be called? The compiler can't call both constructors as that may cause one object to contain faulty values.

Upvotes: 0

Luchian Grigore
Luchian Grigore

Reputation: 258568

Having union members with explicit constructors is disallowed by the standard, it has nothing to do with the union being a member or a nested type.

The following would also fail to compile:

struct X
{
    X() {};
};
union Y
{
    X k;
};

Upvotes: 3

Related Questions