C ++: strange appearance of "query for member X of Y that is not in class Z"

The following program compiled with g ++ 4.6 gives an error

request for member 'y' in 'a2', which is of non-class type 'A<B>(B)' 

in the last line:

 #include <iostream> template <class T> class A { public: T y; A(T x):y(x){} }; class B { public: int u; B(int v):u(v){} }; int main() { int v = 10; B b1(v); //works A<B> a1(b1); //does not work (the error is when a2 is used) A<B> a2(B(v)); //works //A<B> a2((B(v))); std::cout << a1.yu << " " << a2.yu << std::endl; } 

As you can see from the working version included in the code, adding parentheses around the arguments of constructor A solves the problem.

I saw some related errors caused by interpreting the constructor call as a function declaration, for example, when creating an object without an argument to its constructor, but with curly braces:

 myclass myobj(); 

but it seems to me that

 A<B> a2(B(v)); 

cannot be interpreted as a function declaration.

Can anyone explain to me what is going on?

+4
source share
4 answers

This is the case of the most unpleasant parsing , where the compiler interprets A<B> a2(B(v)) as a function declaration. Such that:

A<B> is the return type
a2 is the name of the function
B is the type of argument
v is the name of the argument

So when you do

 std::cout << a1.yu << " " << a2.yu << std::endl; 

The compiler does not consider a2.yu as a class, so you get a non-class type error.

Also, since a double bracket is not allowed in a function declaration , version A<B> a2((B(v))); works because the compiler no longer interprets it as a function declaration, but as a variable declaration.

+8
source

I think you get a bit from "the most unpleasant parsing", which means that A<B> a2(B(v)); parsed as a function declaration instead of a variable declaration.

+2
source

As you can see from the following code example:

 int a (int(v)) { return v; } int main() { std::cout << a(5); //prints 5 } 

This line is indeed a declaration. In this example, the parameter is of type int and is called v . Referring to your code, the parameter is of type B and is called v . That's why you get this behavior when you use double parentheses: because they are one and the same!

+2
source

This function declaration:

 A<B> a2(B(v)); //is same as: A<B> a2(B v); //consider: int foo(int v); int foo(int (v)); 
+2
source

All Articles