问题
The following program, compiled with g++ 4.6, yields the error
request for member ‘y’ in ‘a2’, which is of non-class type ‘A<B>(B)’
at its 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.y.u << " " << a2.y.u << std::endl;    
}
As can be seen from the working variant included in the code, adding parentheses around the arguments of the constructor of A solves the problem.
I have seen some related errors caused by a the interpretation of a constructor invocation as a function declaration, like when creating an object with no argument to its constructor, but with braces:
myclass myobj();
but it seems to me that
A<B> a2(B(v));
cannot be interpreted as a function declaration.
Someone can explain to me what is happening?
回答1:
It's a case of most vexing parse where the compiler interprets A<B> a2(B(v)) as the declaration of a function. Such that:
A<B> is the return typea2 is the function nameB is the type of the argumentv is the argument name
So, when you are doing
std::cout << a1.y.u << " " << a2.y.u << std::endl;
The compiler does not think of a2.y.u as a class, that's why you are getting the non-class type error.
Also, since double parenthesis aren't allowed in a function declaration, the version A<B> a2((B(v))); works because the compiler doesn't interprets it as a function declaration anymore, but as a variable declaration.
回答2:
I think you're getting bit by the "most vexing parse", meaning that A<B> a2(B(v)); is getting parsed as function declaration instead of a variable declaration.
回答3:
It is a function declaration:
A<B> a2(B(v));
//is same as:
A<B> a2(B v);
//consider:
int foo(int v);
int foo(int (v));
回答4:
As seen in the following code sample:
int a (int(v)) {
    return v;
}
int main() {
    std::cout << a(5); //prints 5
}
That line is indeed a declaration. In this example, the parameter is of type int and named v. Relating that to your code, the parameter is of type B and is named v. That's why you get the similar behaviour when you use double parentheses: because it's the same thing!
来源:https://stackoverflow.com/questions/11138543/c-bizarre-occurrence-of-request-for-member-x-of-y-which-is-of-non-class-type