Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 248
user1001031 Avatar asked Dec 08 '22 23:12

user1001031


1 Answers

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.

like image 83
Mesop Avatar answered Dec 11 '22 11:12

Mesop