Member of Union has User-Defined Constructor
Asked Answered
V

1

1

For the following code:

class Foo{
    int foo;
public:
    Foo() : foo(13) {}
    int getFoo() const { return foo; }
};

union Bar{
    Foo fBar;
    double dBar;
};

I believe this is fully legal in C++. http://en.cppreference.com/w/cpp/language/union#Explanation says:

If two union members are standard-layout types, it's well-defined to examine their common subsequence on any compiler

And thus in gcc I can do this:

Bar bar = { Foo() }

When I try this in Visual Studio 2008 I get the error:

error C2620: member Bar::fBar of union Bar has user-defined constructor or non-trivial default constructor

Error C2620 states:

A union member cannot have a default constructor.

What's going on here? Was this ever a C++ requirement, I thought that Standard Layout was the only requirement? Is there a work around for this?

Vassell answered 17/10, 2016 at 13:55 Comment(11)
VS2008 does not include a C++11 compiler. You'll need to upgrade if you want to use language features introduced in C++11Hemicrania
I would go with 2015 update 3 if you want the most C++11 conformance you can get.Mikaelamikal
@CaptainObvlious That wasn't a C++11 feature, And the error is still listed in Visual Studio 2013: msdn.microsoft.com/en-us/library/43ae0055(v=vs.120).aspxVassell
@Mikaelamikal That wasn't a C++11 feature, And the error is still listed in Visual Studio 2013: msdn.microsoft.com/en-us/library/43ae0055(v=vs.120).aspxVassell
@JonathanMee Unions did change from C++98/03 to C++11. Before they had to only have POD objects. Now they are expanded. Also note that MSVS2013 still lacked C++11 features. See this where it has Unrestricted unionsMikaelamikal
@Mikaelamikal That's exactly the answer that I'm looking for. Would you be willing to post that as an answer?Vassell
@JonathanMee You can self answer if you want. Honestly I do not see its worth as the cppreference link you have states that you are quoting is in a C++11 section block so it is telling you right there that it is a C++11 feature.Mikaelamikal
@Mikaelamikal The reason for this question is that my en.cppreference.com/w/cpp/language/union#Explanation quote is not in a C++11 block. This could be a bug? I don't mind self answering though. Whenever the rule went into effect Microsoft didn't adopt it until Visual Studio 2015.Vassell
@JonathanMee Oh look at that. I will write something up.Mikaelamikal
Yes, it's a C++11 feature and the section immediately before the one you linked to on cppreference.com points that out.Hemicrania
@CaptainObvlious You're saying the quote: "If members of a union are classes with user-defined constructors and destructors, to switch the active member, explicit destructor and placement new are generally needed." Qualifies the next statement as if to say: "C++11 allows the use of members with user defined constructors and destructors."Vassell
M
2

In C++98/03 the C++ standard stated in 9.5

[...]If a POD-union contains several POD-structs that share a common initial sequence (9.2), and if an object of this POD-union type contains one of the POD-structs, it is permitted to inspect the common initial sequence of any of POD-struct members;[...]

And this was changed in C++11 to

[...]If a standard-layout union contains several standard-layout structs that share a common initial sequence (9.2), and if an object of this standard-layout union type contains one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of standard-layout struct members;[...]

So before C++11 you could only use a POD type inside a union which means MSVS 2008 is giving you the right error. In order to use the new type of union you need to get the version of MSVS that supports that change. From this MSDN article we can see under the section for Unrestricted unions that that change was not made until version 2015.

You are either going to have to upgrade or change the class to be a POD type

Mikaelamikal answered 17/10, 2016 at 15:11 Comment(2)
So it would appear that en.cppreference.com has the wrong of it then? So my quote in the question should have been contained in the C++11 block?Vassell
@JonathanMee Looks that way. The jist is right but the terminology changed.Mikaelamikal

© 2022 - 2024 — McMap. All rights reserved.