可变参数模板的声明点

2023-12-01

什么时候可变参数模板被视为“声明”?这可以在 clang++ 3.4 下编译,但不能在 g++ 4.8.2 下编译。

template <typename T>
const T &sum(const T &v) { return v; }

template <typename T, typename ... Ts>
auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...));

template <typename T, typename ... Ts>
auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...)) {
    return v + sum(params...);
}

int main() {
    sum(1, 2, 3);
}

显然 g++ 不会匹配尾随返回类型中的函数本身。 g++ 4.8.2 的错误是:

sum.cpp: In function 'int main()':
sum.cpp:13:16: error: no matching function for call to 'sum(int, int, int)'
     sum(1, 2, 3);
                ^
sum.cpp:13:16: note: candidates are:
sum.cpp:2:10: note: template<class T> const T& sum(const T&)
 const T &sum(const T &v) { return v; }
          ^
sum.cpp:2:10: note:   template argument deduction/substitution failed:
sum.cpp:13:16: note:   candidate expects 1 argument, 3 provided
     sum(1, 2, 3);
                ^
sum.cpp:8:6: note: template<class T, class ... Ts> decltype ((v + sum(sum::params ...))) sum(const T&, const Ts& ...)
 auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...)) {
      ^
sum.cpp:8:6: note:   template argument deduction/substitution failed:
sum.cpp: In substitution of 'template<class T, class ... Ts> decltype ((v + sum(sum::params ...))) sum(const T&, const Ts& ...) [with T = int; Ts = {int, int}]':
sum.cpp:13:16:   required from here
sum.cpp:5:74: error: no matching function for call to 'sum(const int&, const int&)'
 auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...));
                                                                          ^
sum.cpp:5:74: note: candidate is:
sum.cpp:2:10: note: template<class T> const T& sum(const T&)
 const T &sum(const T &v) { return v; }
          ^
sum.cpp:2:10: note:   template argument deduction/substitution failed:
sum.cpp:5:74: note:   candidate expects 1 argument, 2 provided
 auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...));
                                                                      ^

附录:如果我删除可变参数模板的声明,clang++ 和 g++ 都会出错。

补充2:我看到以前有人问过类似的问题。我想这里真正的问题是为什么它适用于一种编译器而不适用于另一种编译器。另外,我可以通过使用 sum() 的非原始参数在 POI 处强制 ADL 来使其与 g++ 一起工作。

附录 3:这在 clang++ 和 g++ 下都有效:

class A {
};
A operator+(const A &, const A &) {
    return A();
}

template <typename T>
const T &sum(const T &v) { return v; }

/*
template <typename T, typename ... Ts>
auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...));
*/

template <typename T, typename ... Ts>
auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...)) {
    return v + sum(params...);
}

int main() {
    //sum(1, 2, 3);
    sum(A(), A(), A());
}

As 这个问题的答案(由Praetorian提供)表明,只有在返回类型之后声明才完整,并且GCC是正确的。我相信 clang 的行为也是允许的,但它不可移植。链接中的答案给出了使用特征类的解决方法,这通常可以完成这项工作,但它有点尴尬并且容易出错(因为您必须在单独的表达式中构造返回类型,这可能与函数略有不同表达)。另一种可能的解决方法是使您的函数成为类模板的静态成员(然后添加一个转发到静态模板成员的自由函数)。

您可以考虑另一种解决方法,这在您的第二个示例中有所暗示,该示例适用于两种编译器。你打电话时sum() on A,您正在应用用户定义的类型作为参数。这涉及到参数相关查找,这会导致模板生成第二次查找以下重载sum()在命名空间中A(这恰好是全局命名空间,与sum()),这允许它在实例化期间找到可变参数函数模板。

因此,如果您可以将参数之一安排为始终需要 ADL 的用户定义类型,则可以依靠重载解析的第二阶段在完全声明后找到可变参数模板。所以,也许这样的东西可能会满足您的需求:

namespace sum_impl {
    struct Dummy { };

    template <typename T>
    T const &sum_helper(Dummy, T const &v) { return v; }

    template <typename T, typename ... Ts>
    auto sum_helper(Dummy d, T const &v, Ts const &...params)
            -> decltype(v + sum_helper(d, params...)) {
        return v + sum_helper(d, params...);
    }

    template<typename... P>
    auto sum( P const &...p )
            -> decltype( sum_helper( Dummy{}, p... ) {
        return sum_helper( Dummy{}, p... );
    }
}
using sum_impl::sum;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

可变参数模板的声明点 的相关文章

  • C# 测试活动的互联网连接。 Ping google.com

    C 2008 我正在使用此代码来测试互联网连接 因为我的应用程序必须登录到网络服务器 但是 如果用户互联网连接失败或电缆被拔出 我必须通知用户 Ping www google com to check if the user has a i
  • 为什么这个 oracle 批量插入不起作用?

    我正在尝试将一些数据批量插入到 oracle 数据库中 我按照文档中的示例进行操作 this DataBaseAccess new OracleConnection connString var dataAdapter new Oracle
  • C# 并行与并行线程代码性能

    我一直在测试 System Threading Parallel 与线程的性能 我很惊讶地发现并行比线程花费更长的时间来完成任务 我确信这是由于我对并行的了解有限 我刚刚开始阅读 我想我会分享一些片段 如果有人可以向我指出并行代码比线程代码
  • NHibernate IQueryable 集合作为 root 的属性

    我有一个根对象 它有一个集合属性 例如 I have a Shelf object that has Books Now public class Shelf public ICollection
  • 在目标 VS 安装时,VSIX 扩展内部使用的 WPF-Log4Net 未输出日志

    当 Log4net 在 VSIX 扩展中使用并安装在另一个目标 VS 上时 它不会记录日志 我有一个 WPF 解决方案 我下载了 log4net dll 添加了 log4net config 并将 复制到输出目录 值设置为 始终复制 log
  • 为什么将 char 传递给函数会改变它在 c 中的值?

    我目前正在关注本作业簿 http www cs bham ac uk exr lectures opsys 10 11 lectures os dev pdf关于构建操作系统 我的目的是写一个64位内核 我已经在文本模式下加载 内核 代码并
  • std::tr1::function 和 std::tr1::bind

    我在使用时遇到问题veryC 类中的复杂 C 函数 重写 C 函数是not一个选项 C函数 typedef void integrand unsigned ndim const double x void fdata unsigned fd
  • 我的 WPF 应用程序未触发 MainWindow_Loaded

    我目前正在关注Pluralsight C Fundamentals Part 1并在Classes and Objects视频部分指导我在 Visual Studio 中创建一个新的 WPF 应用程序并填写代码 这导致以下结果 namesp
  • 修剪 UIImage 边框

    这是我想要修剪的图像的示例 我想去掉图像周围的边框 在本例中是顶部和底部的黑条 我在Github上找到了一个库 CKImageAdditions https github com cmkilger CKImageAdditions 但是它似
  • 多维数组和指向指针的指针

    创建多维数组时char a 10 10 根据我的书 它说你必须使用类似于char a 10 将数组传递给函数 为什么必须这样指定长度 您不是只是将双指针传递给 with 并且该双指针不是已经指向分配的内存吗 那么为什么参数不能是char a
  • 如何删除实体框架6中的多对多关系

    如果将项目连接为多对多关系 则从数据库中删除项目时会出现问题 我的数据库看起来像 Project lt JobInProject gt Job ProjectID JobInProjectID JobID ProjectID JobID 主
  • Identity Server 4:添加访问令牌的声明

    我正在使用 Identity Server 4 和隐式流 并且想要向访问令牌添加一些声明 新的声明或属性是 tenantId 和 langId 我已将 langId 添加为我的范围之一 如下所示 然后通过身份服务器请求 但我也获得了tena
  • 为什么这个单独的定义会导致错误?

    挑战 我有这段代码无法编译 你能找出问题所在吗 有一次让我很头疼 header namespace values extern std string address extern int port cpp file std string v
  • 三种 System.Drawing 方法表现出缓慢的绘制或闪烁:解决方案?或其他选择?

    我正在通过 System Drawing 进行一些绘图 但遇到了一些问题 我将数据保存在队列中 并将该数据绘制 绘制 到三个图片框中 此方法填充图片框 然后滚动图形 所以不要在以前的绘图上绘制 并且逐渐看起来更混乱 我找到了两种绘制图表的解
  • 从视图模型调用方法的命令

    好吧 我倾向于避免使用命令 因为它们总是让我感到困惑 但我正在进行一个新项目 并且正在尝试正确构建它 并且在我看来没有任何代码隐藏 基本上我现在想做的就是连接一个按钮来触发一个命令 在我的视图模型上执行一些操作 但不知何故 如此简单的事情仍
  • 使用 _Alignas 进行结构成员对齐

    我想知道以下问题 是新的吗 Alignas结盟 C11 中的说明符适用于结构成员吗 我一直假设这么多 但彻底阅读了 N1570 公开草案似乎表明对齐说明符不能 出现在一个说明符限定符列表 这就是我所期望的 如果得到支持的话 我已经读过几遍语
  • 如何创建和使用类箭头运算符? [复制]

    这个问题在这里已经有答案了 因此 在到处研究之后 我似乎找不到如何创建类箭头运算符 即 class Someclass operator gt 我只需要知道如何使用它并正确使用它 它的输入是什么 它返回什么 我如何正确地声明 原型化它 运算
  • Gridview 错误:对 Bind 的调用格式不正确

    我有以下 gridview 代码
  • 将多个 Blob 输入传递到 QueueTrigger Azure 函数的最佳方法

    问题 触发后 生成 3 个 XML 文件 完成后将它们通过 ftp 传输到站点 目前的方法 我有一个 HTTP 触发器 Azure 函数 运行时将构造 3 个 XML 文件并将它们保存到 Azure 存储 Blob 容器中 由于有多个输出
  • 如何使用 Ioc Unity 注入依赖属性

    我有以下课程 public interface IServiceA string MethodA1 public interface IServiceB string MethodB1 public class ServiceA IServ

随机推荐

  • 在 IE 8 中加载页面后添加 Google +1 按钮

    我现在正在开发一个网站 需要先构建一个 URL 然后再将按钮放在页面上 它的工作原理如下 var googleplus
  • 替代已弃用的 NXOpenEventStatus?

    我需要获取 OSX 10 13 上鼠标的跟踪速度 我在互联网上找到了这段代码 但 NXOpenEventStatus 已被弃用 IOHIDGetAccelerationWithKey 也是如此 是否有其他方法 include
  • 代码复杂度

    一个只有一个循环的程序的复杂度是多少 是 log n 吗 有人可以给我一些关于估计代码复杂性的想法吗 嗯 这实际上取决于该循环中发生的情况 该循环是线性时间 即 O n int sum 0 foreach int i in SomeColl
  • 将 dict 值四舍五入到小数点后 2 位

    我很难四舍五入字典中的值 我拥有的是这样的字典列表 y a 80 0 b 0 0786235 c 10 0 d 10 6742903 a 80 73246 b 0 0 c 10 780323 d 10 0 a 80 7239 b 0 782
  • 使用正则表达式识别字母/数字组合并存储在字典中

    import pandas as pd df pd DataFrame Date This 1 A16 19 person is BL 17 1111 and other dont Z 1 12 do here but NOT 12 24
  • 如何使用 MVVM Light Toolkit 打开新窗口

    我在 WPF 应用程序中使用 MVVM Light 工具包 我想知道从现有窗口打开新窗口的最佳方法是什么 我有这个MainViewModel 它负责MainWindow我的申请 现在在MainView 单击按钮后 我想在其顶部打开第二个窗口
  • Python 检查项目是否在列表中

    我正在尝试迭代两个列表并检查 list 1 中的项目是否在 list 2 中 如果list 1中的项目在list 2中 我想打印list 2中的项目 如果该项目不在 list 2 中 我想打印 list 1 中的项目 下面的代码部分完成了这
  • 查找 HashMap 中保存最小整数值的键

    我正在为需要学习最常用单词的年轻学生创建一个教育游戏 我随机从列表中选择三个单词 将它们显示在屏幕上 播放这三个单词之一的录音 然后学生必须选择已发音的单词 我记录他们猜对每个单词的次数 这样我就可以设定一个标准 规定何时向学生介绍新单词
  • 使用 terraform 循环 for_each 嵌套资源

    我正在尝试使用多个订阅来配置多个 Azure 服务总线主题 我能够创建主题 但无法循环订阅变量来创建订阅 locals servicebus topic 1 subscription subscription1 subscription2
  • Google Drive SDK - Java 示例不起作用

    我正在尝试使用官方 Java 示例来熟悉 Google Drive API 然而 在浪费了几个小时并尝试设置示例两次之后 我仍然无法按预期使用它 它不会显示文件的内容 而是在 FileServlet svc 路径 中引发 404 错误 进一
  • Android以编程方式删除Chrome/默认浏览器cookie、历史记录、搜索

    就像标题一样 我想通过在我的应用程序中编码来删除Android浏览器的cookie和缓存 浏览器不是网页视图 谢谢你 In your Activity or Service add ContentResolver cR getContent
  • 找不到容器 XXX 中的项目 MY_ARTIFACT_NAME

    当尝试根据教程配置 MS Release Manager 时将应用程序部署到 Azure 修改为在主机代理上使用发布构建工件时出错 我收到以下异常 该项目MY ARTIFACT NAME在容器 56811 中找不到 这会导致发布被拒绝 我已
  • 如何加载 Sass::Script::Functions 模块的扩展?

    我正在尝试根据此建议扩展 Sass Script Functions 模块 https gist github com 481261 dd07a52829886ab1ad0875a8895f0100c4b925ab 问题是 我应该将 sas
  • 交换两个字符串指针

    我必须在 C 中使用 char 并且我想通过仅交换指针来在它们之间交换 到数组而不是一次一个字符 所以我写了这段代码 include
  • 如何使用 sed/grep 提取两个单词之间的文本?

    我正在尝试输出一个包含字符串中两个单词之间的所有内容的字符串 input Here is a String output is a Using sed n Here String p 包括端点 但我不想包括它们 GNU grep 还可以支持
  • 如何获取tf.exe(TFS命令行客户端)?

    要获取 tf exe 程序 我需要安装的最少软件数量是多少 你需要安装团队探索者 最好安装与您正在使用的 TFS 版本相匹配的 Team Explorer 版本 例如如果您使用的是 TFS 2010 则安装 Team Explorer 20
  • 如何使用绝对路径获取有关 git 存储库的信息

    我正在编写一些脚本来获取有关我在本地设置的 git 存储库的信息 使用一个简单的例子可以最好地解释这一点 machine anon mkdir test machine anon cd test machine test anon mkdi
  • 创建用于静态初始化布局描述的 API/元编程 DSL

    我需要创建一个 C 元编程 DSL API 来描述通用数据布局 我想要静态初始化数据结构描述 即没有动态内存分配 最好在 ROM 部分分配 我还不太熟悉 C 11 功能 但我知道与提供的旧标准相比 您可以在初始化 静态 方面做更多的事情 我
  • 如何在 tkcalendar (Python) 中获取 DateEntry 的选定日期?

    我有一个 tkcalendar 它是日历 DateEntry 的预定义小部件 并且我正在尝试获取用户为 DateEntry 选择的日期 而可以使用以下方法提取日历小部件的选定日期 选择 获取 但我找不到 DateEntry 的任何内容 我尝
  • 可变参数模板的声明点

    什么时候可变参数模板被视为 声明 这可以在 clang 3 4 下编译 但不能在 g 4 8 2 下编译 template