草庐IT

c++ - 用于参数包扩展的 "pattern"的定义,尤其是在函数调用中

coder 2024-02-10 原文

我了解到,在包含参数包的模式的右边出现省略号(...)时,该模式对于包中的每个参数都会扩展一次。但是,尽管我能够找到扩展了模式的孤立示例,但是却无法找到组成模式的定义。从我所看到的,空格在模式的定义中不起作用,但是括号起作用。例如,在此示例中:

template<typename ... Ts>
void func(Ts)
{
    do_something(validate(Ts)...);
}
do_something行将扩展为:
    do_something(validate(var1), validate(var2), validate(var3))

如果Ts恰好代表三个变量。相比之下:
    do_something(validate(Ts...));

将扩展为:
    do_something(validate(var1, var2, var3));

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

更新:为了限制我的问题的范围,我想集中讨论在函数调用中出现模式的情况。我已经相应地编辑了标题。抱歉,我从一开始就不清楚。

最佳答案

[temp.variadic]/4下的标准中定义了一种模式:(通过@t.c.)

A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list (described below). The form of the pattern depends on the context in which the expansion occurs. Pack expansions can occur in the following contexts:



以上来自标准草案的引言谈到了链接中描述的语法的哪一部分是正在扩展的“模式”。要理解它,您需要知道如何描述C++语法以及在标准文本本身中如何使用C++语法的异常(exception)情况。但是,如果您具有基本的BNF知识并且有一定的耐心,则可以进行练习。这些名称通常也很有用。

但是,您可以使用...并大致了解它,而不必那么深入。

通用规则很简单:您以通常的方式解析了一些C++语法(称为模式),其中将一堆类型视为单个类型,将一堆文字视为单个文字。然后,在它的结尾,您有一个...扩展器。然后,它将紧接在(模式)之前的C++语法中的所有未扩展包打包并对其进行扩展。

这在每种情况下如何工作是不同的;这不仅是宏扩展。上面列举了...有效的上下文;扩展的影响在有效的每个点都在标准中列出。

...的最平常的用例中,模式是一个表达式,并且如果表达式的每个拷贝都由,(不是operator,,而是另一个“正常”的)分隔开,则该表达式会被扩展,通常是在列表的上下文中预期的事情(函数调用,初始化列表等)。

在模板参数列表(通常在其中引入一个包)等中有函数参数声明上下文(其中...既扩展了函数参数的类型,并引入了新的参数名包),等等。
sizeof...有点奇怪:对于sizeof...,它计算()中传递的包中有多少个元素。这是不同的,因为...不适用于“左侧的结构”。

对于alignas(X...),我们最终得到alignas(X@0), alignas(X@1), ...(其中@0是我对该包中第一个元素的伪代码),因为alignas(X@0, X@1, ...)不是有效的C++(同样在下面的评论中为@ T.C。)。

为了继承,它创建了一组基类。对于mem-initializer-lists,它使您可以将ctor参数传递给所说的基类包。对于lambda,它为您提供了有限的包捕获(在我最后一次检查扩展的情况下,表达式捕获还不够完整)。

模式是事物的扩展。重要的是,一个扩展的模式不会被另一个模式扩展器扩展:std::array< Ts, sizeof...(Ts) >...是一包由各种类型组成的数组,每个数组都有许多元素,这些元素由包本身的大小决定。即使sizeof...(Ts)并非“正确”,Ts仍将其()中的...“视为扩展”,因为该语言将Ts中的()定义为...扩展的模式。

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

一般规则是,您将...视为在本地上下文中以适当的方式扩展了左侧的内容,该规则适用于sizeof...除外的所有内容(这是一个神奇的运算符,它告诉您参数包中有多少个元素)。只有在极端情况下,这不会产生一个体面的模型。以我的经验,更糟糕的是,它将导致代码在您认为应该编译时无法编译;您可以在这种情况下了解解决方法。就像,记住一条裸露的语句“没有本地上下文”,因此您不能执行a = std::get<Is>(tup))...;,而是要解决的方法(void)(int[]){0,(a = std::get<Is>(tup)),0)...};(可能必须类型化int[]),在这里我们提供了一个上下文(创建数组)以使包扩展在其中工作。

C++ 1z的fold表达式是另一个奇怪的地方,...在左边不适用;在这里,他们想要扩展二进制运算符,因此“在左边”没有通常的“一元”扩展有意义。

关于c++ - 用于参数包扩展的 "pattern"的定义,尤其是在函数调用中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36984193/

有关c++ - 用于参数包扩展的 "pattern"的定义,尤其是在函数调用中的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  5. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  6. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  7. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  8. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  9. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  10. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

随机推荐