9

Minimal code example:

struct B { 
  union U {
    struct S {} s;
    int i = 100;
  }
  u;  
};

Now if we declare a B obj; then the obj.u.i is assigned a garbage value instead of 100. See the demo here. (The garbage value differs based on optimization flags etc.).

Is the "In class initialization" feature supposed to work with unions.

  • If yes, then what is the correct syntax? Or is this a g++ bug?
  • If not then what int i = 100; does?
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 2
    [clang](http://coliru.stacked-crooked.com/view?id=6ab1a0f46b2229dfc46dfa6f4f5e3163-6e9f1f680880347f6708b805c806db62) seems happy with your code. – Praetorian Jul 22 '13 at 15:06
  • @Praetorian, Thanks. However, you haven't put the output statements. So here is the correct [clang output](http://coliru.stacked-crooked.com/view?id=542928082d0e3f7d6edd525a7fcfac44-6e9f1f680880347f6708b805c806db62). – iammilind Jul 22 '13 at 15:50

2 Answers2

3

This looks like a GCC bug. The standard says (9.5p2):

At most one non-static data member of a union may have a brace-or-equal-initializer.

Otherwise, the rules are the same as for a regular class.

EDIT: In addition, 12.6.2p8:

In a non-delegating constructor, if a given non-static data member or base class is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then

  • if the entity is a non-static data member that has a brace-or-equal-initializer, the entity is initialized as specified in 8.5;
  • otherwise, if the entity is a variant member (9.5), no initialization is performed;
  • otherwise, the entity is default-initialized (8.5).

Presumably the implicitly defined default constructor counts here. The i member meets the criteria in the first bullet point, so it's initialized like it were a regular class member. The s member matches the second bullet point, so it's left uninitialized.

JohannesD
  • 13,802
  • 1
  • 38
  • 30
  • It does not compile on VS 2010 & 2012, not even the first version, with the error: only static const integral data members can be initialized within a class. Or both compilers have a bug or there is something more... – joy Jul 22 '13 at 15:05
  • @neagoegab Neither of those VS versions support in-class initialization of data members. [clang](http://coliru.stacked-crooked.com/view?id=6ab1a0f46b2229dfc46dfa6f4f5e3163-6e9f1f680880347f6708b805c806db62) is compiling the code with no errors. – Praetorian Jul 22 '13 at 15:07
2

I think it is like that because a union reunites more than one element. Below is the work around syntax:

struct B { 
  union U {
    int i;
  }
  u {100};  
};

int main () {
  B obj;
  std::cout << "obj.u.i = " << obj.u.i << "\n";
}
iammilind
  • 68,093
  • 33
  • 169
  • 336
joy
  • 1,569
  • 8
  • 11
  • 1
    Please stop guessing. Post an answer which you *know*, and can suppport. – Nawaz Jul 22 '13 at 14:42
  • @Nawaz, I belive that I have supported my answer. The alternative is to find it in the standard, but at that you are faster than me :D, but I will update the answer. – joy Jul 22 '13 at 14:47
  • This solution doesn't work with my actual problem, just add `struct S {} s;` inside the `union U` and the program gives [compiler error](http://ideone.com/5tS7q9). I have updated the question accordingly. – iammilind Jul 22 '13 at 14:51
  • @iammilind The workaround is to define a default constructor for `U`: `U() : i(100) {}` instead of using in-class member initialization. – Casey Jul 22 '13 at 15:18