带有逗号运算符和可变参数模板参数包的折叠表达式

时间:2018-11-16 02:48:02

标签: c++ c++17 variadic-templates operator-keyword fold

events

基于c ++运算符docconst { createRemoteFileNode } = require(`gatsby-source-filesystem`); const axios = require('axios'); // Replace ACCESS_TOKEN with your Instagram token const API_URI = `https://app.ticketmaster.com/discovery/v2/events.json?countryCode=AU&size=100&apikey=${API_KEY}`; exports.sourceNodes = async ({ actions, store, cache, createNodeId }) => { const { createNode, createNodeField } = actions; // Fetch data const { data } = await axios.get(API_URI); // use for loop for async/await support for (const event of data._embedded.events) { let fileNode; try { fileNode = await createRemoteFileNode({ url: event.images.url, cache, store, createNode, createNodeId }); } catch (error) { console.warn('error creating node', error); } } }; 从左到右的运算符。它的意思是#include<iostream> using namespace std; template<typename ...Args> void output_argus(Args&&... args) { ((cout << args << '\n'), ...); // #1 (... , (cout << args << '\n')); // #2 } int main() { output_argus(1, "test", 5.6f); } 的意思是','而不是a, b, c, d。如果a,b,c,d是语句,则这一点很重要。

但是,基于折叠表达式doc,对于(((a, b), c),d),应使用一元左折叠

我的问题为什么我的代码中的两个语句都起作用? #2不应该工作吗? 以及如何理解(a, (b, (c, d)))','。和嵌套的折叠表达?

2 个答案:

答案 0 :(得分:6)

假设我们将3个表达式折叠在一个二元运算符上,并进行一元折叠。这里有两个选项:(xs @ ...)(一元右折)和(... @ xs)(一元左折)。

(xs @ ...)扩展到(a @ (b @ c))

(... @ xs)扩展到((a @ b) @ c)

关于表达式a @ (b @ c)(a @ b) @ c之间的区别,我们能说什么?如果@在这些类型上是 associative ,则这两个表达式是相同的。这就是联想的意思。如果您有一个整数参数包,则一元左折叠+和一元右折叠+将具有相同的值(模溢出),因为加法是关联的。另一方面,减法不是关联的。 (xs - ...)(... - xs)的含义截然不同。

同样,C ++中的,运算符是关联的。括号内的表达式没关系。 ((a, b), c)(a, (b, c))都评估并丢弃a,然后评估并丢弃b,然后评估c,这就是结果。为何会出现这种情况,更容易看出是否将表达式简化为字母。

结果,((cout << args << '\n'), ...)(... , (cout << args << '\n'))都做同样的事情,它们实际上都意味着:

cout << args1 << '\n';
cout << args2 << '\n';
// ...
cout << argsN << '\n';

答案 1 :(得分:4)

在链接页面上,您的#1扩展如下:

((cout << args₀ << '\n'), ((cout << args₁ << '\n'), (cout << args₂ << '\n')));

删除一些重复内容以使其更干净:

args₀, (args₁, args₂)

对于#2,扩展可归结为:

(args₀, args₁), args₂

让我们逐步评估每个人。

#1:

args₀  ,  (args₁, args₂)
      ^^^

带下划线的逗号将评估左侧,并打印1。然后评估右侧,评估args₁的打印,打印test,然后评估args₂的打印,打印5.6

#2:

(args₀, args₁)  ,  args₂
               ^^^

带下划线的逗号用于评估左侧。这将触发对另一个逗号的评估,该逗号评估args₀的打印,打印1,然后评估args₁的打印,打印test。现在,带下划线的逗号已完成左侧的评估,并右侧的评估,打印5.6

如您所见,尽管括号的分组不同,但两者对每个参数的求值顺序相同。

请注意,通常这可能并不总是成立。某些运算符,例如+,不像逗号运算符那样具有保证的评估顺序。如果使用这样的运算符代替逗号来连接打印表达式,则编译器最终可以选择以任何顺序评估各个参数打印。