[英]Dependent template names and C++20 ADL
考虑以下示例:
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);
}
Both GCC and Clang fail to compile this code under C++17 standard (with -Werror
), because (according to my understanding) in C++17 ADL doesn't work when explicit template arguments <...>
are present (unless a name is already established作为模板名称),因此foo
是未找到的非依赖名称。
在 C++20 中,ADL 规则发生了变化,显式模板 arguments 不会阻止 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
演示。
我有三个相关的问题:
foo
foo<0>(c)
中的 foo 是否被视为从属名称?foo
foo<0>(c)
中的 foo 是否被视为从属名称?这是P0846 ,它是 C++20 功能。 gcc 似乎还没有实现这一点。
这不是依赖名称与否的问题,而是编译器是否知道foo
引用模板的问题, foo<
是否进行比较或是否开始执行模板参数也是如此。
在 C++17 中,编译器必须已经知道foo
是一个模板名称(您可以通过添加using N::foo;
来完成)才能执行 ADL,在 C++20 中这不再是正确的 - 现在规则是如果 unqualified lookup 找到一个模板或什么都没有,我们也认为它是一个模板。
foo
的依赖并没有因为这篇论文而改变。 在foo<0>(c);
, foo
仍然是一个从属名称。 C++17 [temp.dep]中的规则是:
在以下形式的表达式中:
postfix-expression ( expression-list opt )
其中postfix-expression是unqualified-id , unqualified-id表示从属名称,如果
- 表达式列表中的任何表达式都是包扩展,
- 表达式列表中的任何表达式或花括号初始化列表都是类型相关的,或者
- unqualified-id是一个模板 ID ,其中任何模板 arguments 都依赖于模板参数。
第二个项目符号在这里适用 - c
取决于类型。 C++20 的措辞是一样的。 这里的问题不在于foo
不依赖于 C++17。 只是规则是当我们foo<
时,我们不知道foo
是一个模板,所以它被认为是小于运算符,然后就失败了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.