Can an anonymous union be instantiated in c++? - c++

I have this piece of code:
class test {
private:
union {
double x;
std::vector<double> y;
} amIValid;
};
I wonder if the union instance amIValid is valid?

An unnamed union can be instantiated in C++:
union { int i; double d; } my_thing;
my_thing.i = 3;
// etc.
An anonymous union is an unnamed union that is not instantiated (scroll down). You can access its members directly:
union { int i; double d; };
i = 3;
// etc.
So the answer to the question in the title is that an anonymous union cannot be instantiated because instantiating it means that it is not an anonymous union.

Related

Mutable anonymous struct

I want to define an aggregate with a number of mutable fields (to save it in std::set or std::priority_queue and modify it in future, surely saving the container invariants). I tried the following syntax and it was compiled successfully:
#include <cstdlib>
int
main()
{
struct X
{
mutable struct
{
int i;
int j;
};
};
X const x{};
//x.i = 1;
return EXIT_SUCCESS;
}
Live example for clang 3.8.
But statement x.i = 1; gives an error:
error: cannot assign to variable 'x' with const-qualified type 'const X'
My intention was to group a plenty of sequential fileds and apply mutable keyword to the group.
Is this syntax wrong? If so, what is an intention of compiler makers to allow such a syntax if any?
ADDITIONAL:
Code:
#include <cstdlib>
int
main()
{
struct X
{
mutable struct
{
int i;
int j;
};
void f() const { i = 1; }
};
X const x{};
//x.i = 1;
x.f();
return EXIT_SUCCESS;
}
gives an error too:
error: cannot assign to non-static data member within const member function 'f'
note: member function 'main()::X::f' is declared const here
void f() const { i = 1; }
The trouble comes from the mix between the non-standard (in C++) usage of anonymous struct together with the mutable. The latter is a storage class specifier that is meant to be used for members and not for types.
Alternative 1: define an intermediate member for your anonymous struct:
You can define a member that will then be mutable, according to the rules of standard C++:
struct X
{
mutable struct
{
int i;
int j;
} y;
};
X const x{};
x.y.i = 1;
Live demo
Alternative 2: make every members in the anonymous struct mutable:
You can otherwise define the members within the struct as being mutable. As the anonymous struct merges these members into the enclosing struct, the mutable property will be passed on:
struct X
{
struct
{
mutable int i;
mutable int j;
};
};
Online demo
What does the standard say ?
The standatad C++ doen't allow anonymous struct. Anonymous struct is a compiler extension for C11 compatibility.
The C++ standard allows however anonymous unions. But it sets restrictions, notably:
9.5/6: A storage class is not allowed in a declaration of an anonymous union in a class scope.
So when compiling the following code:
struct X
{
mutable union
{
int i;
int j;
};
};
the compiler shall and will issue a very specific error:
prog.cpp:11:13: error: a storage class on an anonymous aggregate in class scope is not allowed
mutable union
I think that it is not consistent to allow using a storage class specifier on an anonymous struct (and apparently ignoring it) and to issues an error for an anonymous union. According to me, this shall be reported as a compiler bug. In anycase, you should adopt alternative 1 (portable & compliant) or alternative 2 (compiler dependent, but more consistent with the standard).

Why does named union inside struct overwriting other struct members?

struct TestStruct
{
int a;
int b;
union
{
char c[2];
int d;
};
};
TestStruct instance;
If I do
instance.a = 100;
instance.b = 200;
instance.d = 300;
everything's fine.
But, If I give union a name:
struct TestStruct
{
int a;
int b;
union ZZZ // Note here!!
{
char c[2];
int d;
};
};
TestStruct instance;
And I do same things again:
instance.a = 100;
instance.b = 200;
instance.ZZZ::d = 300;
then
instance.ZZZ::d = 300;
is overwriting instance.a to be 300, why?!
Additionally, I can not see the union members in debugger watch list if it has a name.
I am using Visual Studio 2008.
When you name the union there is no longer a data member in the class corresponding to d so instance.ZZZ::d = 300; doesn't mean anything. (With VS2012 I get "error C2039: 'ZZZ' : is not a member of 'TestStruct'")
To have a member of a union type you'll have to give it a name.
struct TestStruct
{
int a;
int b;
union ZZZ // Note here!!
{
char c[2];
int d;
} z;
};
instance.a = 100;
instance.b = 200;
instance.z.d = 300;
C++ has a special rule for 'anonymous unions', where an unnamed union type of the form union { member-specification }; also creates an unnamed object. The names of the union's members are injected into the enclosing scope and access the unnamed object's members.
That's what you're getting when you don't name the union type inside your class. But as soon as you give the type a name the union no longer matches that special rule and there's no longer an unnamed union member in the class; You then have to add the union data member normally, by naming the member variable.

Syntax to initialize an anonymous union

If I declare an anonymous union in a function…
void f(int in) {
union { int i; float f; };
// …
}
…does syntax exist to initialize it (other than assigning to i or f in another statement? A quick look at the spec suggests no. The obvious ones don’t compile:
// Nope:
union { int i = in; float f; };
union { int i; float f; } = in;
union { int i; float f; } = {in};
union { int i; float f; }{in};
union { int i; float f; }(in);
This works (at least in gcc 4.7.2):
union { int i; float f; } x = {1};
Notice that the type (i.e. the union) is anonymous but its instanciation is called x.
What you were trying to achieve (e.g. union { int i; float f; }{in};) doesn't compile but suppose it did. Then you would be creating an unnamed object (a temporary) of an unnamed type. The temporary would be destroyed at the end of the expression and, therefore, this statement would have no effect. So what's the point?
See update below -- I'm not sure whether this is a language restriction or a compiler limitation.
In the absence of designated initializers (added to C in 1999, so far nonexistent in C++ as far as I know), an initializer for a union can only specify a value for the first named member:
union { int i; float f; } obj = { 42 }; // sets obj.i to 42
C, as of the 1999 standard, provides designated initializers that let you initialize any named member you like:
union { int i; float f; } obj = { .f = 1.25 };
Since C++ doesn't have this feature, you're pretty much out of luck unless you happen to want to initialize the first named member.
Of course you can use an assignment:
union { int i; float f; } obj;
obj.f = 1.25;
which I suggest is a perfectly good workaround. You can do what you want; you just can't do it with the syntax you want.
Giving the union type a name wouldn't be particularly helpful in this case, unless you make it visible in a wider scope and write a function that returns a value of the type:
union u { int i; float f; };
u init_f(float f) { u result; result.f = f; return result; }
// later
u obj = init_f(1.25);
UPDATE :
I wasn't aware of the existence of anonymous union in C++ when I wrote the above. C11 permits anonymous unions and structs, but only as members of an enclosing union or struct. C++11 permits an anonymous union object to be defined, as in this example from the standard:
void f() {
union { int a; const char* p; };
a = 1;
p = "Jennifer";
}
g++ 4.7.2 seems not to permit anonymous union objects to be initialized. For example, this:
int main() {
union {
int i;
float f;
} = { 42 };
}
results in the following errors with g++ -std=c++11:
c.cpp: In function ‘int main()’:
c.cpp:5:5: error: expected ‘;’ after union definition
c.cpp:5:7: error: expected primary-expression before ‘=’ token
I don't see anything in section 9.5 of the C++11 standard that forbids initializers for anonymous unions, which makes me think that this is a limitation of g++, presumably to be corrected in a future release.
Whether this limitation is imposed by the language or by g++, you can work around it either by giving the union a name:
union { int i; float f; } obj = { 42 };
(but then you have to refer to obj.i and obj.f rather than just i and f), or by using an assignment rather than an initializer:
union { int i; float f; };
i = 42;
(I'll clean up this answer once we resolve whether this restriction is imposed by the language or by the compiler.)

Namespace scope vs scope inside class

There is this code:
namespace N {
struct B {
void f() {
i;
j;
}
int i;
};
int j;
}
int main() {
return 0;
}
Variable i is found but variable j is not. How does it work that variable in the class can be used before it is declared but the same does not work for namespace? How i is found - compiler parses first all class to find all members then bind it with references from member functions?
Indeed, the bodies of member functions (as well as variable initializers) are processed in a later phase than the class definition. You can check for yourself that the "declare before use" rule is still in full effect for class members, by trying to use members in other member declarations:
struct B
{
char c[sizeof i];
int i;
};
Demonstration: http://ideone.com/v1ksio
struct B2
{
decltype(i) f();
int i;
};
This also affects usage of the class itself which requires a complete type.
struct B
{
static char c[sizeof (B)];
};
Demonstration: http://ideone.com/Z9XOzm
But this is ok, because variable initializers are processed when the construction definitions are, where all members are known and the type is complete:
struct B
{
unsigned r{sizeof s};
unsigned s{sizeof (B)};
};

a point from ISO document: based on Anonymous Unions

Point from ISO C++ Standard: section 9.5, para 4, line 1:
"A union for which objects or pointers are declared is not
an anonymous union."
Example :
struct X {
union {
int i;
double d;
} ;
int f () { return i;}
};
int main() { return 0; }
IAm expecting an error from this example according to the above point
but GCC,SUN compiler CC,EDG,etc are not showing error
iam expecting this error// error : cannot directly access "i"
please ..conform above example program is correct are wrong
This would make the union not anonymous:
struct X {
union {
int i;
double d;
} *p;
int f () { return i;} // !Nyet.
};
Cheers & hth.,
To add to what Alf is saying, the purpose of the anonymous union language in the C++ spec is to allow scoping of the unions members. If you have a named union inside a struct:
struct X {
union {
int i;
double d;
} varname;
};
i is not a member of the struct X. i is a member of varname, which itself is a member of struct X.
However, if the union doesn't have a member variable declared, then i would have to be accessed directly as a member of X. This can only work if the union has no name (no variables are declared with the union definition). Such unions are called "anonymous unions".