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.)
Related
Is there a nice way to have a non static value as default argument in a function? I've seen some older responses to the same question which always end up in explicitly writing out the overload. Is this still necessary in C++17?
What I'd like to do is do something akin to
class C {
const int N; //Initialized in constructor
void foo(int x = this->N){
//do something
}
}
instead of having to write
class C {
const int N; //Initialized in constructor
void foo(){
foo(N);
}
void foo(int x){
//do something
}
}
which makes the purpose of the overload less obvious.
One relatively elegant way (in my opinion) would be to use std::optional to accept the argument, and if no argument was provided, use the default from the object:
class C {
const int N_; // Initialized in constructor
public:
C(int x) :N_(x) {}
void foo(std::optional<int> x = std::nullopt) {
std::cout << x.value_or(N_) << std::endl;
}
};
int main() {
C c(7);
c.foo();
c.foo(0);
}
You can find the full explanation of what works/doesn't work in section 11.3.6 of the standard. Subsection 9 describes member access (excerpt):
A non-static member shall not appear in a default argument unless it
appears as the id-expressionof a class member access expression
(8.5.1.5) or unless it is used to form a pointer to member
(8.5.2.1).[Example:The declaration of X::mem1()in the following example
is ill-formed because no object is supplied for the non-static
memberX::a used as an initializer.
int b;
class X {
int a;
int mem1(int i = a);// error: non-static memberaused as default argument
int mem2(int i = b);// OK; useX::b
static int b;
};
I was watching one of Jason Turner's videos and I saw that you can define a type inside a function scope and have it available outside of that scope through function return type deduction.
auto f()
{
struct MyStruct
{
int n;
};
return MyStruct{};
}
int main()
{
auto a = f().n;
return a;
}
Why is this allowed? Is there a paragraph in the C++ 14 standard that allows this?
When trying to get the typeid of MyStruct with clang in compile explorer I saw in the assembly output the type displayed as f()::MyStruct, so there is a scope, but somehow I can access MyStruct outside of that scope. Is this some kind of ADL thing?
No, there's no ADL involved. Since your translation unit contains the definition of the structure, there's no problem in accessing its members.
The important point is that types don't really exist in scopes: names do. And notice that there's no way for you to use the identifier MyStruct instead of auto when declaring a. The name is as inaccessible as it should be. However, as long as you can get at the type without using the inaccessible name, all is fine.
In principle, this is hardly different from using a private member type:
class X
{
struct Hidden
{
int i;
};
public:
Hidden get() const { return {42}; }
};
int main()
{
X x;
auto h = x.get();
assert(h.i == 42);
}
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).
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)};
};
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".