了解std::应用于std::visit内部



https://github.com/google/oboe/blob/e3e93e307456a388a84a6e0d96f9adb240f5918d/apps/fxlab/app/src/main/cpp/native-lib.cpp#L93

std::visit([id](auto &&stack) {
std::function<void(decltype(stack.getType()), decltype(stack.getType()))> f;
int i = 0;
std::apply([id, &f, &i](auto &&... args) mutable {
((f = (i++ == id) ?
args.template buildDefaultEffect<decltype(stack.getType())>() : f), ...);
}, EffectsTuple);
stack.addEffect(std::move(f));
}, enginePtr->functionList);

std::visit将lambda应用于向量functionList。lambda,将其内部的lambda应用于EffectsTuple

然而,我很难理解

((f = (i++ == id) ?
args.template buildDefaultEffect<decltype(stack.getType())>() : f), ...);

最外层的()做什么?第二个自变量...是什么?args.template是什么意思?

((f = (i++ == id) ?
args.template buildDefaultEffect<defaultEffect<decltype(stack.getType())>() : f), ...);

这是一个逗号折叠执行包扩展。这是一种遍历元组中非统一类型元素的方法。

如果你可以迭代一组非均匀元素:

int i=0;
for...(auto& arg:args...){
if (i!=id){
++i;
continue;
}
f=arg.template buildDefaultEffect<defaultEffect<decltype(stack.getType())>();
break;
}

这是他们想要编写的代码。但他们做不到。

因此,他们使用逗号折叠执行来为args中的每个arg生成与上面循环正文等效的内容。

并且在";什么都不做";他们做CCD_ 6。

我自己会做:

((i++ == id) ?
f=args.template buildDefaultEffect<defaultEffect<decltype(stack.getType())>() : nullptr), ...);

这既更清晰又更有效。

或者,foreach_arg是一个有用的写入替代方案。或者制作一个n大小的函数指针数组,每个指针做一个循环体,只运行一个。

第二个参数是什么。。。?

(foo(args), ...)是一个折叠表达式,使用逗号运算符,相当于(foo(arg0), foo(arg1), .., foo(argn))

args.template是什么意思?

template用于消除依赖类型的<的含义歧义

否则,它将被解析为

(args.buildDefaultEffect < decltype(stack.getType())) > ()

查看在哪里以及为什么要输入模板和类型名称关键字。

...是逗号运算符的右折叠。该代码本质上是为具有请求id的args变量调用buildDefaultEffect函数,将返回值分配给f,然后将f添加到具有stack.addEffect的堆栈中。

基本上,代码扩展到类似的东西

(f = f, f = f, /*i == id*/ f = args.buildDefaultEffect(stack.getType()), f = f, f = f);
stack.addEffect(f);

最新更新