【问题标题】:Dependent template names and C++20 ADL从属模板名称和 C++20 ADL
【发布时间】: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),因为(根据我的理解)当显式模板参数 &lt;...&gt; 是 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.

我有三个相关的问题:

  1. 哪个编译器是正确的,为什么?
  2. 在 C++17 中,foo&lt;0&gt;(c) 中的 foo 是否被视为从属名称?
  3. 在 C++20 中,foo&lt;0&gt;(c) 中的 foo 是否被视为从属名称?

【问题讨论】:

  • Fwiw: gcc trunc 在 C++20 模式下也可以编译它,所以他们似乎在 10.2 之后添加了该功能。

标签: c++ templates language-lawyer c++20 argument-dependent-lookup


【解决方案1】:

这是P0846,这是一个 C++20 特性。看来 gcc 还没有实现这一点。

这不是依赖名称与否的问题,而是编译器是否知道foo 指的是模板,foo&lt; 是在做比较还是开始做模板参数的问题。

在 C++17 中,编译器必须已经知道 foo 是一个模板名称(您可以通过添加 using N::foo; 来完成)才能执行 ADL,在 C++20 中这不再适用- 现在的规则是,如果非限定查找找到一个模板或什么都没有,我们也认为它是一个模板。


foo 的依赖并没有因为这篇论文而改变。在foo&lt;0&gt;(c); 中,foo 仍然是从属名称。 C++17 中[temp.dep] 中的规则是:

在一个表达式中:

postfix-expression ( expression-list<sub>opt</sub> )

后缀表达式是一个unqualified-idunqualified-id表示一个依赖名如果

  • 表达式列表中的任何表达式都是包扩展,
  • expression-list 中的任何表达式或 braced-init-lists 都是类型相关的,或者
  • unqualified-id 是一个 template-id,其中任何模板参数都依赖于模板参数。

第二个项目符号在这里适用 - c 是依赖于类型的。 C++20 的措辞是一样的。这里的问题不是 foo 不依赖于 C++17。只是规则是当我们foo&lt; 时,我们不知道 foo 是一个模板,所以它被认为是小于运算符,然后就失败了。

【讨论】:

  • 但是foo 是从属名称吗?如果所有名称都属于两类,这应该是一个有效的问题。
  • @Evg 在 C++17 中,它也是依赖的……如果查找碰巧找到了一个模板,使得这个表达式可以正确解析。名称的“依赖性”并没有因为这篇论文而改变。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-29
  • 1970-01-01
  • 2019-10-27
  • 2021-12-03
  • 1970-01-01
相关资源
最近更新 更多