C ++ list not recognized by compiler

Can someone explain why the following code does not compile (on g ++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-49))?

struct X { public: enum State { A, B, C }; X(State s) {} }; int main() { X(X::A); } 

The message I get:

jjj.cpp: In the function 'int main ()':
jjj.cpp: 10: "XX :: A" is not a static member of "struct X"
jjj.cpp: 10: there is no corresponding function to call "X :: X ()"
jjj.cpp: 1: candidates: X :: X (const X &)
jjj.cpp: 5: X :: X (X :: State) `

Is this bad code or compiler error?

The problem is solved by Neil + Conrad. See Neil Comments below.

+4
source share
6 answers
 X(X::A); 

s is considered as a function declaration. If you really need this code, use:

 (X)(X::A); 
+8
source

You forgot the variable name in your definition:

 int main() { X my_x(X::A); } 

Your compiler confuses your code because it cannot syntactically distinguish this from a function declaration (returns X and passes X::A as an argument). When in doubt, the C ++ compiler always ambiguously advocates for the declaration.

The solution is to introduce redundant parentheses around X , since the compiler forbids parentheses around types (as opposed to constructive calls, etc.):

 (X(X::A)); 
+10
source

Just to make it clear what is happening. Look at this example

 int main() { float a = 0; { int(a); // no-op? a = 1; } cout << a; } 

What will come out? Well, it will print 0 . int(a) above can be parsed in two different ways:

  • Paste into int and discard result
  • Declare a variable named a . But ignore the parentheses around the identifier.

The compiler, when a situation arises when an expression using a function type expression is used in an expression, and it also looks like an declaration, it will always be perceived as an announcement. When it cannot be syntactically a declaration (the compiler will examine the entire string to determine this), it will be considered an expression. Thus, we assign the inner a above, leaving the outer a equal to zero.

Now that’s your case. You are trying (accidentally) to declare an identifier called a in a class named X :

 X (X::A); // parsed as XX::A; 

Then the compiler continues to moan about the undeclared default constructor, because the static, as it assumes, is constructed by default. But even if you had a default constructor for X, it is of course still erroneous, because none of a is a static member of X, and the staticness of X can be defined / declared in the block area.

You can make this look like an ad by following a few steps. First, you can break up the whole expression, making it no longer look like an ad. Or just undo the type that is superimposed. Both of these ambiguities were mentioned in other answers:

 (X(X::A)); (X)(X::A) 

When trying to actually declare an object, there is a similar but clear ambiguity. Take a look at this example:

 int main() { float a = 0; int b(int(a)); // object or function? } 

Since int(a) can be either a declaration of a parameter named a or an explicit conversion (cast) of a variable float to int, the compiler again decides that it is a declaration. So we declare a function called b that takes an integer argument and returns an integer. There are several possibilities to eliminate this, based on the values ​​indicated above:

 int b((int(a))); int b((int)a); 
+1
source

You must declare the object as

 X x(X::A); 

Error in the code.

0
source

Any of these two lines work for me:

 X obj(X::A); X obj2 = X(X::A); 

As Neil Butterworth points out, X(X::A) considered a function declaration. If you really want an anonymous object, (X)(X::A) construct the object X and delete it immediately.

0
source

You could, of course, just do something like this:

 int main() { // code { X temp(X::A); } // more code } 

This would be more readable and basically have the same effect.

0
source

All Articles