【发布时间】:2021-03-21 07:46:25
【问题描述】:
考虑以下示例:
namespace N {
template<class>
struct C { };
template<int, class T>
void foo(C<T>);
}
template<class T>
void bar(N::C<T> c) {
foo<0>(c);
}
int main() {
N::C<void> c;
bar(c);
}
GCC 和 Clang 都无法在 C++17 标准下编译此代码(使用 -Werror),因为(根据我的理解)当显式模板参数 <...> 是 C++17 ADL 时不起作用存在(除非已将名称建立为模板名称),因此 foo 是未找到的非依赖名称。
在 C++20 中,ADL 规则发生了变化,显式模板参数不会阻止 ADL。现在看来foo 成为一个依赖名称,应该可以通过ADL 解析。但是,对于这段代码的有效性,GCC 和 Clang 有不同的看法。 CLang 编译它没有错误,但 GCC (10.2, -std=c++2a) 抱怨:
error: 'foo' was not declared in this scope; did you mean 'N::foo'?
在 C++17 模式下,Clang 会产生以下警告:
warning: use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension
Demo.
我有三个相关的问题:
- 哪个编译器是正确的,为什么?
- 在 C++17 中,
foo<0>(c)中的foo是否被视为从属名称? - 在 C++20 中,
foo<0>(c)中的foo是否被视为从属名称?
【问题讨论】:
-
Fwiw: gcc trunc 在 C++20 模式下也可以编译它,所以他们似乎在 10.2 之后添加了该功能。
标签: c++ templates language-lawyer c++20 argument-dependent-lookup