C++: bizarre occurrence of “Request for member X of Y which is of non-class type Z”

删除回忆录丶 提交于 2019-12-14 01:09:32

问题


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 type
a2 is the function name
B is the type of the argument
v 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!