当前位置: 首页 > 知识库问答 >
问题:

依赖模板名称和C 20 ADL

王亮
2023-03-14

考虑以下示例:

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中,当显式模板参数

在C 20中,ADL规则有变化,显式模板参数不会阻止ADL。现在看来,foo成为了一个依赖名称,应该可以通过ADL解析。然而,GCC和Clang对本规范的有效性有不同的看法。CLang编译时没有错误,但GCC(10.2,std=c 2a)抱怨:

错误:'foo'未在此范围内声明;您的意思是'N::foo'吗?

在C 17模式下,Clang产生以下警告:

警告:在带有显式模板参数的函数调用中使用不带先验声明的函数模板名称是C 20扩展

演示。

我有三个相关的问题:

  1. 哪个编译器是正确的,为什么
  2. 在C 17中,isfooInfoo

共有1个答案

锺离伟彦
2023-03-14
匿名用户

这是P0846,这是一个C 20功能。gcc似乎还没有实现这一点。

这不是依赖名称与否的问题,而是编译器是否知道foo是否引用了模板,foo也是如此

在C 17中,为了执行ADL,编译器必须知道foo是一个模板名称(可以通过使用N::foo;添加来实现),在C 20中,这不再是真的-现在的规则是,如果非限定查找找到模板或什么都没有找到,我们也会将其视为模板。

本文的研究结果没有改变foo的依赖性。在foo中

在以下形式的表达式中:

后缀表达式(表达式列表)

如果后缀表达式是一个不合格的id,则不合格的id表示依赖的名称,如果

  • 表达式列表中的任何表达式都是包扩展,

第二个项目符号适用于此处-c取决于类型。C 20的措辞是相同的。这里的问题并不是说foo不依赖于C 17。只是规则是当我们

 类似资料:
  • 我有一些代码无法编译,我将其简化为以下最低版本: 在魔杖盒上看到 Clang(9.0.0)拒绝了这一点: Clang说是一个依赖的模板名称是对的吗?VS 2017没有问题。GCC(9.2.0)也拒绝该代码,但错误消息更加模糊: 按照叮当的建议改变冒犯的路线 修复Clang和GCC的编译。VS2017也接受此版本。 解决方案似乎很简单,但如果我重新排序函数调用: 或从 中删除参数: 错误消失了。 这

  • 当我尝试编译这段代码时 对于g 4.8.2,我得到以下错误消息 (与3.4版本的叮当声几乎相同)。 首先,我认为代码是正确的,应该进行编译,因为foobar是模板声明中的一个依赖名称,应该仅在模板实例化的第二阶段进行查找。在最后一行中完成此操作时,已声明“foobar(int)”。顺便说一句,当我取消注释最上面的行时,代码会编译,但这两个声明都在实例化之前,所以这应该无关紧要。 其次,我觉得错误信

  • 问题内容: 在(和)包中,具有以下签名: 到底是干什么用的?我已经扫描了文档(还有一些资料),但无济于事。我只是用一个空字符串实例化所有模板,这似乎没有什么不同。我为什么要打扰一个名字? 即使是命名模板,两者似乎是等效的: https://play.golang.org/p/wKzCHdLf2S 问题答案: 毫无疑问,模板的名称就是为模板 命名 。 到底有什么好处呢?只要您不想 引用 该模板,就没

  • 我在一个ARM模板中有两个相互依赖的Azure资源:一个密钥库和一个service fabric集群。 是否有一种方法可以引用service fabric集群的对象ID来提供给密钥库的访问策略,是否有一种方法可以在不硬编码任何值的情况下生成密钥库中的机密?理想情况下,我们只知道秘密名称,并且只将该秘密名称提供给ARM模板中的服务fabric集群。

  • 这是关于cppreference的描述。com说 模板中使用的依赖名称的查找将推迟到模板参数已知时,此时[…]ADL检查从模板定义上下文或模板实例化上下文可见的具有外部链接的函数声明。 与此相反,以下代码段可以使用三个编译器(MSVC、clang、gcc)很好地编译: Foo是CallFoo中的从属名称:它取决于模板参数T。但是,尽管违反了上述两条规则,编译器还是找到了函数Foo。 从的定义或实例

  • 我的Gradle项目中有两个依赖项库: OLD:完全使用lib 新:只有db库(固定库) 它们都拥有相同的数据库连接类,包括包,例如:net。我的公司。常见的dbsq。DBConnector()。 我需要的是确保使用新的db连接类,但由于所需的UTIL的其余部分在新的数据库中不可用,所以保留旧的(可以没有db类)作为依赖项。 是否有可能仅排除/包括依赖项的特定类或包?或者确保相同命名类的“重写”?