C++ [basic.lookup.unqual]/3中的第一个示例

C++ [basic.lookup.unqual]/3中的第一个示例,c++,language-lawyer,C++,Language Lawyer,第一个例子是: inth; void g(); 名称空间N{ 结构A{}; 模板int f(T); 模板int g(T); 模板inth(T); } int x=f(N::A());//确定:查找f时找不到任何内容,f被视为模板名称 int y=g(N::A());//确定:查找g会找到一个函数,g被视为模板名 int z=h(N::A());//错误:h

第一个例子是:

inth;
void g();
名称空间N{
结构A{};
模板int f(T);
模板int g(T);
模板inth(T);
}
int x=f(N::A());//确定:查找f时找不到任何内容,f被视为模板名称
int y=g(N::A());//确定:查找g会找到一个函数,g被视为模板名
int z=h(N::A());//错误:h<不开始模板id

上面的注释似乎表明编译器应该区别对待上面的名称
g
h
的查找,就好像名称
h
不考虑模板id一样。当我使用或GCC编译这个代码段时,我看不到这种差异。该示例试图传达的具体区别是什么?

您正在查看C++20草案,但使用C++17编译器进行测试

非限定模板名称查找是C++20草稿引入并采用的一项新的ADL功能

因此,要尝试使用GCC trunk和
-std=c++2a
():

错误:在'>'标记之前应该有主表达式
12 | int z=h(N::A());//错误:h<不开始模板id
假设确切的错误消息还不完美,最终结果是前两次查找成功


要进行比较,请注意的C++17版本不包含您提到的示例。

Aha。这是一个很好的例子,说明为什么仅仅提及最新的草案措辞有时会适得其反!那不是我得到的,没关系。我得到了和你一样的结果。但是你所说的“错误消息还不完美”是什么意思呢?coliru运行GCC 8.2。您想要的功能目前仅在trunk中(9.0+)。我所说的错误消息是指它应该说明
h
不是一个模板。我仍然感到困惑。你说:
它应该说
h`不是一个模板
。但是
g`也不是一个模板。有什么区别?换句话说,为什么编译器会发现
模板int g(T)
N
中,但找不到
模板int h(t)
N
int h;
void g();
namespace N {
  struct A {};
  template <class T> int f(T);
  template <class T> int g(T);
  template <class T> int h(T);
}

int x = f<N::A>(N::A());        // OK: lookup of f finds nothing, f treated as template name
int y = g<N::A>(N::A());        // OK: lookup of g finds a function, g treated as template name
int z = h<N::A>(N::A());        // error: h< does not begin a template-id
error: expected primary-expression before '>' token
   12 | int z = h<N::A>(N::A());        // error: h< does not begin a template-id