参数包扩展的“模式”定义,尤其是在函数调用中

2023-12-31

据我了解,当包含参数包的模式右侧出现省略号 (...) 时,该模式将为包中的每个参数扩展一次。然而,尽管我能够找到模式及其扩展的孤立示例,但我无法找到模式构成的定义。据我所知,空格在模式的定义中不起任何作用,但括号却起作用。例如,在这个例子中:

template<typename ... Ts>
void func(Ts)
{
    do_something(validate(Ts)...);
}

the do_something行将扩展为:

    do_something(validate(var1), validate(var2), validate(var3))

if Ts恰好代表三个变量。相比之下:

    do_something(validate(Ts...));

将扩展为:

    do_something(validate(var1, var2, var3));

显然,括号与确定模式的开始和结束位置有关。我还可以看到空白没有。但这只能让我到目前为止。我想确切地知道模式的构成是什么,以及如何扩展它。我尝试搜索 C++ 标准,但发现太多“参数包”实例,无法使其有效。有人可以给我“模式”的定义,或定义的链接,或两者兼而有之吗?

更新:为了限制我的问题的范围,我想重点关注函数调用中出现模式的情况。我已相应地编辑了标题。抱歉我从一开始就没有说清楚。


A pattern标准中定义如下[温度变量]/4 http://eel.is/c++draft/temp.variadic#4: (via @t.c. https://stackoverflow.com/users/2756719/t-c)

A 包扩展由一个pattern和一个省略号,其实例化会在列表中产生零个或多个模式实例化(如下所述)。模式的形式取决于扩展发生的上下文。包扩展可能发生在以下环境中:

  • 在函数参数包中 ([dcl.fct http://eel.is/c++draft/dcl.fct]);模式是参数声明 http://eel.is/c++draft/dcl.fct#parameter-declaration没有省略号。
  • In a template parameter pack that is a pack expansion ([temp.param http://eel.is/c++draft/temp.param]):
    • 如果模板参数包是参数声明 http://eel.is/c++draft/dcl.fct#parameter-declaration;模式是参数声明 http://eel.is/c++draft/dcl.fct#parameter-declaration没有省略号;
    • 如果模板参数包是类型参数 http://eel.is/c++draft/temp.param#type-parameter with a 模板参数列表 http://eel.is/c++draft/temp#template-parameter-list;图案是对应的类型参数 http://eel.is/c++draft/temp.param#type-parameter没有省略号。
  • In an 初始化列表 http://eel.is/c++draft/dcl.init#initializer-list ([dcl.init http://eel.is/c++draft/dcl.fct]);该模式是一个初始化子句 http://eel.is/c++draft/dcl.init#initializer-clause.
  • In a 基本说明符列表 http://eel.is/c++draft/class.derived#base-specifier-list(子句[派生类 http://eel.is/c++draft/class.derived];该模式是碱基说明符 http://eel.is/c++draft/class.derived#base-specifier.
  • In a 内存初始化列表 http://eel.is/c++draft/class.base.init#mem-initializer-list ([类.base.init http://eel.is/c++draft/class.base.init]) 为一个内存初始化器 http://eel.is/c++draft/class.base.init#mem-initializer whose 内存初始化器 ID http://eel.is/c++draft/class.base.init#mem-initializer-id表示基类;模式是内存初始化器 http://eel.is/c++draft/class.base.init#mem-initializer.
  • In a 模板参数列表 http://eel.is/c++draft/temp.names#template-argument-list ([temp.arg http://eel.is/c++draft/temp.arg]);该模式是模板参数 http://eel.is/c++draft/temp.names#template-argument.
  • In a 动态异常规范 http://eel.is/c++draft/except.spec#dynamic-exception-specification ([除.spec http://eel.is/c++draft/except.spec]);该模式是type-id http://eel.is/c++draft/dcl.name#type-id.
  • In an 属性列表 http://eel.is/c++draft/dcl.attr.grammar#attribute-list ([dcl.attr.语法 http://eel.is/c++draft/dcl.attr.grammar]);该模式是一个属性 http://eel.is/c++draft/dcl.attr.grammar#attribute.
  • In an 对齐说明符 http://eel.is/c++draft/dcl.attr.grammar#alignment-specifier ([dcl.对齐 http://eel.is/c++draft/dcl.align]);模式是对齐说明符 http://eel.is/c++draft/dcl.attr.grammar#alignment-specifier没有省略号。
  • In a 捕获列表 http://eel.is/c++draft/expr.prim.lambda#capture-list ([表达式.prim.lambda http://eel.is/c++draft/expr.prim.lambda]);该模式是capture http://eel.is/c++draft/expr.prim.lambda#capture.
  • In a sizeof...表达 ([表达式.sizeof http://eel.is/c++draft/expr.sizeof]);该模式是一个标识符 http://eel.is/c++draft/lex.name#identifier.
  • In a 折叠表达 http://eel.is/c++draft/expr.prim.fold#fold-expression ([表达式.prim.fold http://eel.is/c++draft/expr.prim.fold]);模式是强制转换表达式 http://eel.is/c++draft/expr.cast#cast-expression包含未扩展的参数包。

上面引用的标准草案谈论了什么语法的一部分链接中描述的是正在扩展的“模式”。要理解它,您需要了解 C++ 语法是如何描述的以及标准文本本身如何使用它的例外情况;但是,如果您有基本的 BNF 知识并且有一点耐心,您就可以解决这个问题。这些名称通常也很有用。


但是,您可以使用...并且大多数人都明白它,但没有深入到那么深。

The general规则很简单:你有一些 C++ 语法(称为pattern)以通常的方式解析,其中一组类型被视为单个类型,一组文字被视为单个文字。然后,最后,你有一个...扩展器。然后,它会获取紧接之前的 C++ 语法位中的所有未展开包(pattern)并展开它。

它在每种情况下的工作原理是不同的;这不仅仅是宏观扩张。所处的背景...上面列举的是有效的;标准中在每个有效点都列出了扩展的影响。

在最普通的用例中...,该模式是一个表达式,并且该表达式被扩展,就好像它是由, (not operator,,但另一个“正常”的),通常在需要一系列事物的上下文中(函数调用、初始化列表等)。

有函数参数声明上下文(其中...两者都扩展了函数参数的类型,并在模板参数列表中引入了新的参数名称包(通常在其中引入了参数包)等。

sizeof...有点奇怪:对于sizeof...它计算在包中传递的元素有多少个()。这工作方式不同,因为...不适用于“左侧结构”。

For alignas(X...),我们最终得到alignas(X@0), alignas(X@1), ... (where @0是我的包的第一个元素的伪代码),如alignas(X@0, X@1, ...)不是有效的 C++(在下面的评论中再次@T.C.)。

对于继承,它创建一组基类。对于 mem-initializer-lists,它允许您将 ctor 参数传递给所述基类包。对于 lambda,它为您提供了有限的包捕获(我上次检查的扩展表达式捕获并不完整)。

模式是扩展的东西。重要的是,扩展模式不会被另一个模式扩展器扩展:所以std::array< Ts, sizeof...(Ts) >...是一组不同类型的数组,每个数组的元素数量由数组本身的大小决定。sizeof...(Ts)“算作扩展”Ts in its (), 虽然...不是“正确的”,因为语言定义了Ts in the ()作为扩展的模式....

一般情况下的模式不能称为表达式,因为类型不是表达式,而某些模式是表达式(或至少扩展为表达式列表)。并且在某些情况下,...将类型模式扩展为类型的扩展包(就像在 throw 表达式中一样)。

一般规则是,你对待...因为在本地上下文中以适当的方式扩展左边的东西,几乎适用于所有东西,除了sizeof...(这是一个神奇的运算符,可以告诉您参数包中有多少个元素)。只有在无法产生像样模型的极端情况下才会出现这种情况。根据我的经验,最糟糕的是,它会导致代码在您认为应该编译时无法编译;在这种情况下,您可以学习解决方法。就像,记住一个简单的陈述“没有本地上下文”,所以你不能这样做a = std::get<Is>(tup))...;,而是解决方法(void)(int[]){0,(a = std::get<Is>(tup)),0)...};(可能必须输入int[]),我们为包扩展提供一个上下文(创建一个数组)。

C++1z 的折叠表达式是另一个奇怪的地方,其中...不适用于左侧;在这里,他们想要对二元运算符进行扩展,因此“在左侧”不像通常的“一元”扩展那样有意义。

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

参数包扩展的“模式”定义,尤其是在函数调用中 的相关文章

  • 将 new 与 decltype 一起使用

    T t T is an implementation detail t new T want to avoid naming T to allow for flexibility t new decltype t error cannot
  • 单元测试验证失败

    我正在运行我的单元测试PostMyModel路线 然而 在PostMyModel 我用的是线Validate
  • 在路由mvc 4中添加公司名称

    我一直在尝试为 Facebook 等用户提供在 URL 中添加公司名称的选项 http localhost 50753 MyCompany Login 我尝试过不同的网址 但没有成功 routes MapRoute name Default
  • 如何在另一个应用程序中挂钩 api 调用

    我正在尝试挂钩另一个应用程序的 ExtTextOut 和 DrawTextExt GDI 方法调用 我知道我需要使用 GetProcAddress 来查找 gdi32 dll 中那些方法的地址 并用我的函数的地址覆盖我想要挂钩的进程中的地址
  • linq 中使用字符串数组 c# 的 'orderby'

    假设我有一个这样的方法定义 public CustomerOrderData GetCustomerOrderData string CustomerIDs var query from a in db Customer join b in
  • 在 C# 中调用 C++ 库 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有很多用 C 编写的库 我想从 C 调用这些库 但是 我遇到了很多问题 我想知道是否有书籍或指南告诉我如何做到这一点 Dll导入 htt
  • 运行需要 MySql.Data 的内置 .NET 应用程序

    我在运行我编写的内置 NET 应用程序时遇到问题 我的应用程序使用最新的 MySql 连接器 该连接器安装在我的系统上 当我尝试将其添加为引用时 该连接器显示为 NET 4 Framwork 组件 当我在环境中以调试模式运行应用程序时 一切
  • 检测到堆栈崩溃

    我正在执行我的 a out 文件 执行后 程序运行一段时间 然后退出并显示消息 stack smashing detected a out terminated Backtrace lib tls i686 cmov libc so 6 f
  • Gwan C#,如何获取HTTP标头?

    我需要它来重写 url 以了解我正在处理哪个友好的 url 用于用户代理和其他东西 EDIT public class Gwan MethodImplAttribute MethodImplOptions InternalCall exte
  • 在 omp 并行 for 循环中使用 unique_ptr 会导致 SEG.FAULT

    采取以下代码 include
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 使用查询表达式对 List 进行排序

    我在使用 Linq 订购这样的结构时遇到问题 public class Person public int ID get set public List
  • 使用 C# 和 wpf 创建类似 Dock 的应用程序

    我需要创建一个与我们购买笔记本电脑时获得的应用程序类似的应用程序 仅当鼠标指针到达窗口顶部时它才可见 那么我怎样才能使用 C 4 0 来做到这一点呢 http www notebookcheck net uploads pics win2
  • 搜索实体的所有字段

    我正在尝试在客户数据库上实现 多功能框 类型的搜索 其中单个查询应尝试匹配客户的任何属性 这是一些示例数据来说明我想要实现的目标 FirstName LastName PhoneNumber ZipCode Mary Jane 12345
  • 在 OpenGL 中渲染纹理 1 到 1

    所以我想做的是使用 OpenGL 和 C 将纹理渲染到平面上 作为显示图像的一种方式 但是我需要确保在渲染纹理时没有对纹理进行任何处理 抗锯齿 插值 平滑 模糊等 这是 OpenGL 处理渲染纹理的默认方式吗 或者是否需要设置一些标志才能禁
  • 逆向工程 ASP.NET Web 应用程序

    我有一个 ASP NET Web 应用程序 我没有源代码 该 bin 包含 10 个程序集和一个 compiled 文件 我在 App Code dll 上使用 Reflector 它向我显示了类和命名空间之类的东西 但它太混乱了 有没有什
  • 在 C#.NET 中安全删除文件

    在我正在做的一个项目中 我想为用户提供 安全 删除文件的选项 例如 用随机位或 0 覆盖它 在 C NET 中是否有一种简单的方法可以做到这一点 效果如何 你可以调用系统内部删除 http technet microsoft com en
  • 使用 using 声明时,非限定名称查找如何工作?

    根据 C 标准 这是格式错误还是格式良好 namespace M struct i namespace N static int i 1 using M i using N i int main sizeof i Clang 拒绝它 GCC
  • INotifyPropertyChanged 和 propertyName

    我一直不确定它的含义propertyName实施时INotifyPropertyChanged 所以一般来说你实现INotifyPropertyChanged as public class Data INotifyPropertyChan
  • 结构化绑定的用例有哪些?

    C 17 标准引入了新的结构化绑定 http en cppreference com w cpp language structured binding功能 最初是proposed http www open std org jtc1 sc

随机推荐

  • 如何停靠弹出窗口?

    我有一个包含 3 个主要小部件的应用程序 我也有一个弹出窗口QDockWidget 我正在尝试获取QDockWidget停靠到底部小部件的右半部分 但正如您在下图中看到的 我可以停靠窗口的唯一位置是应用程序的边缘 我怎样才能做到这一点QDo
  • 闪亮的传单地图弹出窗口正在提取错误的数据

    由于某种原因 Shiny传单应用程序上分配给多边形的弹出窗口提取了应分配给多边形的错误信息 似乎多边形已放置在地图上 然后以不同的顺序分配多边形属性 任何想法将不胜感激 server lt function input output ses
  • Google Cloud Load Balancer - 子域重定向到存储桶中的特定文件夹

    目前我们有以下需求 每个用户都可以在 Google 存储桶下拥有自己的子域和文件夹 其中包含应通过此子域提供的内容 例如 domain user1 example com gt bucket example com user1 index
  • 如何将表中的某些列复制到另一个mysql

    我有两张桌子 例如 table 1 A B C D E F G H I J table 2 A C D E G H J K L M N O P 我必须将一些列从表 2 复制到表 1 我尝试的是 INSERT INTO table 1 C D
  • json_encode PHP 对象及其受保护的属性

    有什么方法可以设置 PHP 对象 以便当我尝试将它们转换为 JSON 时 它们所有受保护的属性都会显示出来 我读过其他答案建议我添加一个toJson 函数到对象 但这可能并不能真正帮助我很多 在大多数情况下 我有一个对象数组 并对数组本身执
  • 在 Windows 窗体上的窗口一侧添加按钮

    我想在 C 上的 Windows 窗体一侧添加按钮 在外面 当窗口移动时 按钮应该一起移动 例如 我看到两个选择 要么将按钮放在单独的表单中 然后通过编码将两个表单粘在一起Move有可能Resize events 或者更简单 制作表格透明的
  • 在新行中添加 max(value)+1,这会是一个问题吗?

    在 SQL Server 表中 我有以下两列 RowId 主键 数字 标识列和自动插入 MailId 非键 数字 非标识 非自动插入 邮件 ID 可以重复 如果是新的 MailId 我将检查 max MailId 1 并将其插入新行中 如果
  • 如何在gridview中间歇性地展示横幅广告

    I am developing an android app that will have a screen similar to the following image 请注意单元格之间的横幅广告 由于 GridView 不支持这种跨列
  • 为什么在 epoll 中推荐使用非阻塞套接字

    我正在尝试学习如何将 epoll 用于 tcp 服务器应用程序 因为我期望有很多连接 我尝试检查示例和教程 他们总是建议使用 设置在 epoll 中添加的套接字为非阻塞套接字 为什么 对于级别触发的 epoll 非阻塞套接字可以帮助最大限度
  • C# Groupby 然后在分割 CSV 后求和(无标题)

    阅读了各种帖子后 我认为我已经接近得到我想要的结果 但 总和 部分给出了错误的答案 我怀疑这是由于我调用 总和 的方式造成的 因为我的 csv 文件没有列标题 csv 文件包含以下内容 222 1 223 2 222 1 224 2 222
  • 偏移GPS坐标的公式/算法

    我以纬度 经度的形式提供 GPS 坐标 并希望将它们偏移距离和角度 例如 如果我偏移 新坐标是多少45 12345 7 34567沿方位 104 度行驶 22 公里 Thanks 对于大多数应用 这两个公式之一就足够了 给定径向和距离的纬度
  • 收到错误 /bin/sh: 1: 源: 未找到

    我正在尝试构建 docker 并安装 nvm 一些代码行 RUN curl https raw githubusercontent com creationix nvm v0 25 0 install sh bash RUN source
  • 使用 Visual Studio 扩展设置光标位置

    我正在编写自己的 Visual Studio 2010 扩展 它应该可以帮助我浏览一个相当大的解决方案 我已经有一个基于对话框的 VS 扩展 它根据某些搜索条件显示类名和函数名 我现在可以单击此类 方法 然后我就可以打开正确的文件并跳转到该
  • C# OpenGL字体显示

    我正在Windows中使用Tao框架开发2D CAD应用程序 我想使用 Windows 库中的字体来显示绘图信息 除此之外 我想旋转缩放我的文本 对于位图字体我无法做到这一点 我进行了 OpenGL 字体调查 http www opengl
  • SQL-合并两个具有不同日期值的表

    我正在开发一个在网站上显示股票信息的项目 我想问一下如何在SQL中合并两个表 假设我们有表1 stock id date p high p low 3 2013 02 26 100 80 3 2013 02 25 100 80 3 2013
  • 如何使用python获取一列数据中包含的特定行的时间差

    这里我有一个包含时间和三个输入的数据集 这里我用panda来计算时差 代码是 data Time different pd to timedelta data time astype str diff 1 dt total seconds
  • 为什么要创建“隐式解包选项”,因为这意味着您知道有一个值?

    为什么要创建 隐式解包可选 而不是仅创建常规变量或常量 如果您知道它可以成功解包 那么为什么首先要创建一个可选呢 例如 这是为什么 let someString String this is the string 将比以下更有用 let s
  • 代码高尔夫:井字棋

    Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动 按字符数发布您的最短代码 以检查玩家是否获胜 如果获胜 是哪一个 假设变量中有一个整数数组b
  • 重命名 ASP.NET Identity 表时出现重复的外键

    我遵循了以下建议这个问题 https stackoverflow com questions 19460386 how can i change the table names when using visual studio 2013 a
  • 参数包扩展的“模式”定义,尤其是在函数调用中

    据我了解 当包含参数包的模式右侧出现省略号 时 该模式将为包中的每个参数扩展一次 然而 尽管我能够找到模式及其扩展的孤立示例 但我无法找到模式构成的定义 据我所知 空格在模式的定义中不起任何作用 但括号却起作用 例如 在这个例子中 temp