繁体   English   中英

从属模板名称和 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);
}

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

演示

我有三个相关的问题:

  1. 哪个编译器是正确的,为什么?
  2. 在 C++17 中, foo foo<0>(c)中的 foo 是否被视为从属名称?
  3. 在 C++20 中, 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-expressionunqualified-idunqualified-id表示从属名称,如果

  • 表达式列表中的任何表达式都是包扩展,
  • 表达式列表中的任何表达式或花括号初始化列表都是类型相关的,或者
  • unqualified-id是一个模板 ID ,其中任何模板 arguments 都依赖于模板参数。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM