C++:奇怪的出现"请求Y成员X的非类型Z"

use*_*031 4 c++ most-vexing-parse

使用g ++ 4.6编译的以下程序会产生错误

request for member ‘y’ in ‘a2’, which is of non-class type ‘A<B>(B)’
Run Code Online (Sandbox Code Playgroud)

在最后一行:

#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;    
}
Run Code Online (Sandbox Code Playgroud)

从代码中包含的工作变量可以看出,在A的构造函数的参数周围添加括号可以解决问题.

我已经看到一些由构造函数调用解释为函数声明引起的相关错误,比如在创建一个没有参数的构造函数的对象时,但是使用大括号:

myclass myobj();
Run Code Online (Sandbox Code Playgroud)

但在我看来

A<B> a2(B(v));
Run Code Online (Sandbox Code Playgroud)

不能解释为函数声明.

有人可以向我解释发生了什么事吗?

Mes*_*sop 8

这是一个最令人烦恼的解析案例,编译器将其解释A<B> a2(B(v))为函数的声明.这样:

A<B>返回类型
a2是函数名称
B,参数的类型
v是参数名称

所以,当你在做的时候

std::cout << a1.y.u << " " << a2.y.u << std::endl;
Run Code Online (Sandbox Code Playgroud)

编译器不认为a2.y.u是一个类,这就是你得到non-class type错误的原因.

此外,由于函数声明中不允许使用双括号,因此版本A<B> a2((B(v)));可以工作,因为编译器不再将其解释为函数声明,而是作为变量声明.