带有两个参数包的函数模板重载解析

2024-02-27

考虑以下代码:

#include<iostream>

template<class..., class... T>
int f(T...) { return 1; }

template<class... T>
int f(T...) { return 2; }

int main()
{
    std::cout << f(1);
}

它编译并打印1在 gcc 8.2 上,但由于调用而无法在 clang 7 上编译f(1)模棱两可。

如果调用被替换为f()两个编译器都无法编译,声称调用不明确。

如果参数包class... T被替换为一个简单的参数class T (and T... with T),两个编译器也都声称存在歧义。

第一个示例中哪个编译器符合标准?我想这可以归结为函数模板的特定部分排序规则,或者以这种方式使用双参数包是否已经格式错误?

Edit:

我的理解是,双包本身并不是格式错误的,因为在我的阅读中,如果第二个包可以从函数参数中推导出来, [temp.param] 17.1/15 似乎明确允许这种情况,这似乎是因为这T...函数参数包。

还可以显式指定第一个参数包的参数,但不能显式指定第二个参数包的参数,因此并不总是出现(在模板参数推导之后)至少一个参数包为空的情况。我不确定这是否会使程序格式错误,因为我不知道如何阅读,例如[temp.res] 17.7/8.3 在这种情况下。

gcc 和 clang 似乎都适合双参数包本身,例如当第二个函数模板重载被删除时,两个编译器都会打印1。但这可能是一个情况格式错误,无需诊断.

此外,我假设通过类模板参数推导,可变参数类模板可以定义可变参数构造函数模板,这意味着类似于我的双参数包示例的构造函数候选者,并且据我了解,相同的重载解析和模板参数推导需要放在那个背景下。这个问题是由具有这种设置的另一个问题引发的:可变参数类模板推导在 gcc 8.2 中失败,用 clang 和 msvc 编译 https://stackoverflow.com/questions/53356903/variadic-class-template-deduction-fails-with-gcc-8-2-compiles-with-clang-and-ms另请参阅对此的讨论:推导指南和带有可变参数模板构造函数的可变参数类模板 - 参数包长度不匹配 https://stackoverflow.com/questions/43430921/deduction-guides-and-variadic-class-templates-with-variadic-template-constructor

现在我也找到了问题的答案推导指南和可变参数模板 https://stackoverflow.com/questions/44338584/deduction-guide-and-variadic-templates我认为这意味着 gcc 是错误的,并且调用应该被认为是不明确的,但我想验证一下这是否同样适用于这里。我也欢迎更详细的推理,因为函数模板部分排序规则对我来说似乎非常不清楚。


这里有两个问题。


First, [温度扣除部分]/12 https://timsong-cpp.github.io/cppwp/temp.deduct.partial#12(我也引用这个例子,因为它与你的相似)说:

在大多数情况下,如果并非所有模板参数都有值,则推导会失败,但出于部分排序的目的,如果模板参数未在用于部分排序的类型中使用,则模板参数可能会保持没有值。 [ 注意:在非推导上下文中使用的模板参数被视为已使用。 — 尾注 ] [ 示例:

template <class T> T f(int);            // #1
template <class T, class U> T f(U);     // #2
void g() {
  f<int>(1);                            // calls #1
}

—《示例结束》]

用于部分排序的类型是T...根据[温度扣除部分]/3 https://timsong-cpp.github.io/cppwp/temp.deduct.partial#3:

用于确定排序的类型取决于完成部分排序的上下文:

  • 在函数调用的上下文中,使用的类型是函数调用具有参数的函数参数类型。

  • ...

所以第一个未命名模板参数包class...不影响部分排序的结果。由于这两个函数模板没有其他差异,因此两者都不比另一个更专业,从而导致调用不明确。

This may与...有联系错误 49505 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49505 of GCC.


其次,即使第二个函数模板不存在,调用仍然应该是格式错误的。根据[临时参数.显式]/3 https://timsong-cpp.github.io/cppwp/temp.arg.explicit#3:

... A trailing未以其他方式推导的模板参数包将被推导为模板参数的空序列...

Only trailing模板参数包可以推导为空包,而第一个未命名模板参数包class...不是一个trailing模板参数包。

海湾合作委员会 (错误 69623 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69623) 和 铿锵 (错误 26435 https://bugs.llvm.org/show_bug.cgi?id=26435)有这个问题的错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有两个参数包的函数模板重载解析 的相关文章

  • 将处理后的图形绘制到另一个图形中

    我想将一个经过处理的图形绘制到另一个图形中 I have two graphics var gHead Graphics FromImage h var gBackground Graphics FromImage b Transform
  • 如何进行带有偏差的浮点舍入(始终向上或向下舍入)?

    我想以偏置舍入浮动 要么总是向下 要么总是向上 代码中有一个特定的点 我需要这个 程序的其余部分应该像往常一样四舍五入到最接近的值 例如 我想四舍五入到最接近的 1 10 倍数 最接近 7 10 的浮点数约为 0 69999998807 但
  • 获取两个字符串之间的公共部分c# [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要的是获取两个单词之间的共同部分并获取差异 例子 场景1 word1 感言 word2 Test 将返回 公共部分Test 不同之
  • 捕获 foreach 条件中抛出的异常

    我有一个foreach在 foreach 本身的条件下循环期间中断的循环 有没有办法try catch抛出异常然后继续循环的项 这将运行几次 直到异常发生然后结束 try foreach b in bees exception is in
  • ASP .NET MVC,创建类似路由配置的永久链接

    我需要帮助在 MVC 网站中创建类似 URL 路由的永久链接 Slug 已设置为 www xyz com profile slug 代码为 routes MapRoute name Profile url profile slug defa
  • 为什么 BOOST_FOREACH 不完全等同于手工编码的?

    From 增强文档 http www boost org doc libs 1 48 0 doc html foreach html foreach introduction what is literal boost foreach li
  • 是否有与 C++11 emplace/emplace_back 函数类似的 C# 函数?

    从 C 11 开始 可以写类似的东西 include
  • Xamarin Android:获取内存中的所有进程

    有没有办法读取所有进程 而不仅仅是正在运行的进程 如果我对 Android 的理解正确的话 一次只有一个进程在运行 其他所有进程都被冻结 后台进程被忽略 您可以使用以下代码片段获取当前正在运行的所有 Android 应用程序进程 Activ
  • 范围和临时初始化列表

    我试图将我认为是纯右值的内容传递到范围适配器闭包对象中 除非我将名称绑定到初始值设定项列表并使其成为左值 否则它不会编译 这里发生了什么 include
  • 事件日志写入错误

    很简单 我想向事件日志写入一些内容 protected override void OnStop TODO Add code here to perform any tear down necessary to stop your serv
  • 组合框项目为空但数据源已满

    将列表绑定到组合框后 其 dataSource Count 为 5 但组合框项目计数为 0 怎么会这样 我习惯了 Web 编程 而且这是在 Windows 窗体中进行的 所以不行combo DataBind 方法存在 这里的问题是 我试图以
  • C# 创建数组的数组

    我正在尝试创建一个将使用重复数据的数组数组 如下所示 int list1 new int 4 1 2 3 4 int list2 new int 4 5 6 7 8 int list3 new int 4 1 3 2 1 int list4
  • “MyClass”的类型初始值设定项引发异常

    以下是我的Windows服务代码 当我调试代码时 我收到错误 异常 CSMessageUtility CSDetails 的类型初始值设定项引发异常 using System using System Collections Generic
  • UWP 无法在两个应用程序之间创建本地主机连接

    我正在尝试在两个 UWP 应用程序之间设置 TCP 连接 当服务器和客户端在同一个应用程序中运行时 它可以正常工作 但是 当我将服务器部分移动到一个应用程序并将客户端部分移动到另一个应用程序时 ConnectAsync 会引发异常 服务器未
  • 过期时自动重新填充缓存

    我当前缓存方法调用的结果 缓存代码遵循标准模式 如果存在 则使用缓存中的项目 否则计算结果 在返回之前将其缓存以供将来调用 我想保护客户端代码免受缓存未命中的影响 例如 当项目过期时 我正在考虑生成一个线程来等待缓存对象的生命周期 然后运行
  • 内核开发和 C++ [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 从我know https stackoverflow com questions 580292 what languages are windo
  • 同时从多个流中捕获、最佳方法以及如何减少 CPU 使用率

    我目前正在编写一个应用程序 该应用程序将捕获大量 RTSP 流 在我的例子中为 12 个 并将其显示在 QT 小部件上 当我超过大约 6 7 个流时 问题就会出现 CPU 使用率激增并且出现明显的卡顿 我认为它不是 QT 绘制函数的原因是因
  • 在基类集合上调用派生方法

    我有一个名为 A 的抽象类 以及实现 A 的其他类 B C D E 我的派生类持有不同类型的值 我还有一个 A 对象的列表 abstract class A class B class A public int val get privat
  • boost::program_options:带有固定和可变标记的参数?

    是否可以在 boost program options 中使用此类参数 program p1 123 p2 234 p3 345 p12 678 即 是否可以使用第一个标记指定参数名称 例如 p 后跟一个数字 是动态的吗 我想避免这种情况
  • 从类模板参数为 asm 生成唯一的字符串文字

    我有一个非常特殊的情况 我需要为类模板中声明的变量生成唯一的汇编程序名称 我需要该名称对于类模板的每个实例都是唯一的 并且我需要将其传递给asm关键字 see here https gcc gnu org onlinedocs gcc 12

随机推荐