相关模板名称和C ++ 20 ADL [英] 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);
}
GCC和Clang都无法在C ++ 17标准下(使用 -Werror
)编译此代码,因为(据我的理解)在C ++ 17 ADL中,当显式时ADL不起作用模板参数< ...>
存在(除非已将名称建立为模板名称),因此 foo
是未找到的非依赖名称
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 as a template name), so foo
is a non-dependent name that is not found.
在C ++ 20中,ADL规则有所更改,并且显式模板参数不会阻止ADL.现在看来, foo
成为从属名称,应该可以通过ADL解析.但是,GCC和Clang对于此代码的有效性有不同的意见.CLang编译它时没有错误,但是GCC(10.2, -std = c ++ 2a
)抱怨:
In C++20, the ADL rules have changes, and explicit template arguments don't prevent ADL. Now it seems that foo
becomes a dependent name that should be resolvable via ADL. However, GCC and Clang have different opinions about the validity of this code. CLang compiles it without errors, but GCC (10.2, -std=c++2a
) complains:
错误:在此范围内未声明'foo';你是说'N :: foo'吗?
在C ++ 17模式下,Clang会产生以下警告:
In C++17 mode, Clang produces the following warning:
警告:在带有显式模板参数的函数调用中使用没有事先声明的函数模板名称是C ++ 20扩展
演示.
我有三个相关的问题:
- 哪个编译器正确,为什么?
- 在C ++ 17中,是否将
foo< 0>(c)
中的foo
视为从属名称? - 在C ++ 20中,是否将
foo< 0>(c)
中的foo
视为从属名称?
- Which compiler is right and why?
- In C++17, is
foo
infoo<0>(c)
considered as a dependent name? - In C++20, is
foo
infoo<0>(c)
considered as a dependent name?
推荐答案
这是 P0846 ,它是C++ 20功能.看来gcc尚未实现.
This is P0846, which is a C++20 feature. It appears that gcc does not implement this yet.
这不是有关依赖名称的问题,这是编译器是否知道 foo
是否引用模板的问题, foo<
也在做这个问题比较还是开始做模板参数.
It's not a question of dependent name or not, it's a question of does the compiler know that foo
refers to a template or not, and so is foo<
doing a comparison or is it starting to do template parameters.
在C ++ 17中,编译器必须已经知道 foo
是模板名称(您可以通过使用N :: foo; 添加来完成)为了执行ADL,在C ++ 20中不再如此-现在的规则是,如果不合格的查找找到模板或什么都找不到,我们也将其视为模板.
In C++17, the compiler had to already know that foo
was a template-name (which you could accomplish by adding using N::foo;
) in order to perform ADL, in C++20 that's no longer true - now the rule is that if unqualified lookup finds a template or nothing, we also consider it to be a template.
foo
的依赖性没有因本文而改变.在 foo< 0>(c);
中, foo
仍然是从属名称.来自C ++ 17的 [temp.dep] 中的规则是:
The dependence of foo
didn't change as a result of this paper. In foo<0>(c);
, foo
is still a dependent name. The rule in [temp.dep] from C++17 was:
以以下形式的表达式:
In an expression of the form:
后缀表达式(expression-list opt )
其中后缀表达式是不合格ID ,不合格ID 表示从属名称如果
- expression-list 中的任何表达式都是压缩扩展,
- 表达式列表中的任何表达式或 braced-init-lists 都是类型相关的,或者
- 不合格ID 是一个 template-id ,其中任何模板参数都取决于模板参数.
- any of the expressions in the expression-list is a pack expansion,
- any of the expressions or braced-init-lists in the expression-list is type-dependent, or
- the unqualified-id is a template-id in which any of the template arguments depends on a template parameter.
第二个项目符号在这里适用- c
与类型有关.C ++ 20的措辞是相同的.这里的问题不是 foo
不依赖于C ++ 17.只是规则是当我们 foo<
时,我们不知道 foo
是模板,因此被认为是小于-operator,然后失败.
The second bullet applies here - c
is type-dependent. The C++20 wording is the same. The issue here wasn't that foo
wasn't dependent in C++17. It's just that the rule was when we foo<
, we don't know that foo
is a template, so it's considered the less-than-operator, and that then fails.
这篇关于相关模板名称和C ++ 20 ADL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!