-1

Consider following program which is ill formed according to standard

union Test {
    int s{3};
    float f;
    Test() {}            
    Test(float f) : f(f) {} // this should be error
  };

int main() {

}

C++11 standard N3376 clause 12 section 6.2.8 says that ( emphasis mine):

An attempt to initialize more than one non-static data member of a union renders the program ill-formed.

But all the popular 3 compilers ( g++, clang++, MSVC++ ) compiles above program without producing any compiler error or warning. I think it is necessary for a compiler to give diagnosis in this program & program should fail in compilation.

See live demo tested on g++ here.

See live demo tested on clang++ here.

Are all the compilers broken here according to standard ? Is this compiler bug ?

timrau
  • 22,578
  • 4
  • 51
  • 64
Destructor
  • 14,123
  • 11
  • 61
  • 126
  • Naming the parameter `s`, `f` or `data` doesn't change anything. It is used to initialize the member `f`. – Nelfeal Aug 20 '16 at 18:25
  • @Nelxiost, As far as I understand, the OP's problem is not about naming variables, he changed the names trying to make it clearer for readers. The problem is how can that compile in these compilers while the program is considered **ill-formed** in the standard. – Mike Aug 20 '16 at 18:29
  • @Mike: Look what I found something similar here: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1562 – Destructor Aug 20 '16 at 18:30
  • @Mike If you look at the edits, he changed the parameter name back from `data` to `f`. That does not make it clearer for readers. – Nelfeal Aug 20 '16 at 18:32
  • @Mike: It would be better If you can answer this – Destructor Aug 20 '16 at 18:48
  • @Mike Please pay more attention, Destructor didn't change the name to `data`, Nawaz did. He did it to avoid the confusion, because both `s` and `f` are poorly chosen names in this case. Destructor changed it back for no apparent reason. Also, stop trying to guess who downvoted the question. You are wrong assuming I did. – Nelfeal Aug 20 '16 at 18:52
  • @Destructor Since you found a document presenting this exact issue, why don't you answer yourself, providing the link ? It does look like a compiler bug. – Nelfeal Aug 20 '16 at 18:54
  • @destructor: As the DR you cite suggests, the standard wording is changed for C++14, and your experiments specified std=c++14, so the result shouldn't be surprising. As it happens, specifying std=c++11 does not cause an error message to be produced either, which could be considered a defect in a pedantic sort of way. – rici Aug 20 '16 at 18:58

2 Answers2

4

The default constructor lets the s member be initialized, so only one member is initialized there.

The parameterized constructor only initializes the f member, so only one member is initialized there too.

Each constructor lets only one member be initialized, so the program is well-formed.


From §12.6.2/9 of N4594 (the upcoming C++17 standard):

In a non-delegating constructor, if a given potentially constructed subobject 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), then

  • (9.1) — if the entity is a non-static data member that has a default member initializer (9.2) and either

    • (9.1.1) — the constructor’s class is a union (9.3), and no other variant member of that union is designated by a mem-initializer-id...

    [Unrelated text]

What the above quote basically says, is that brace-or-equal-initializer will only execute if there are no mem-initializer-id.

There is also language in the standard that says a union may only have a single brace-or-equal-initializer.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

It is not ill formed as s is a parameter to the constructor

Ed Heal
  • 59,252
  • 17
  • 87
  • 127