相关模板名称和C ++ 20 ADL [英] Dependent template names and C++20 ADL

查看:54
本文介绍了相关模板名称和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扩展

演示.

我有三个相关的问题:

  1. 哪个编译器正确,为什么?
  2. 在C ++ 17中,是否将 foo< 0>(c)中的 foo 视为从属名称?
  3. 在C ++ 20中,是否将 foo< 0>(c)中的 foo 视为从属名称?
  1. Which compiler is right and why?
  2. In C++17, is foo in foo<0>(c) considered as a dependent name?
  3. In C++20, is foo in foo<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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆