gpt4 book ai didi

c++ - `for_each_arg` 的正确用法 - 转发过多?

转载 作者:太空狗 更新时间:2023-10-29 20:58:11 25 4
gpt4 key购买 nike

我真的很高兴发现了for_each_arg(...) ,这使得处理参数包变得更加容易。

template<class F, class...Ts>
F for_each_arg(F f, Ts&&...a) {
return (void)std::initializer_list<int>{(ref(f)((Ts&&)a),0)...}, f;
}

但是,我对它的正确用法感到困惑。有很多参数需要完美转发,但是我是不是进行了无谓的转发?

阅读代码会因过度转发而变得更加困难。

struct UselessContainer
{
// Expects a perfectly-forwarded item to emplace
template<typename T> void add(T&&) { }
};

// Creates an `UselessContainer` already filled with `mArgs...`
auto makeUselessContainer(TArgs&&... mArgs)
{
using namespace std;
UselessContainer result;

for_each_arg
(
[&result, &mArgs...] // Am I capturing the `mArgs...` pack correctly here?
(auto&& mX) // Am I passing the arguments to the lambda correctly here?
{
// Is this `forward` necessary?
result.add(forward<decltype(mX)>(mX));

// Could it be replaced with
// `result.add(forward(mX));`
// ?
},
forward<TArgs>(mArgs)... // I assume this `forward` is necessary.
);

return result;
}

我所有的问题/疑问都在上面代码示例的注释中表达。

最佳答案

您代码中的每个 forward 确实是完美转发所有参数所必需的,直到最后。右值引用的名称是左值,因此除非您每次传递参数时都进行转发,否则值类别信息将丢失。
此外,如果没有显式模板参数列表,则不可能调用 forward,因为模板参数仅用于一个非推导上下文。事实上,在没有显式参数列表的情况下调用的函数模板无法完成这项工作。

您可以尝试使用宏来稍微缩短代码:

#define FORWARD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)

然后变成

for_each_arg
(
// Removed superfluous capture
[&result] (auto&& mX) {
result.add(FORWARD(mX));
},
FORWARD(mArgs)...
);

也可以首先使用宏而不是 for_each_arg:

#define FOR_EACH_ARG(...) (void)std::initializer_list<int>{((__VA_ARGS__),0)...}

FOR_EACH_ARG( result.add(forward<TArgs>(mArgs)) );

关于c++ - `for_each_arg` 的正确用法 - 转发过多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28263000/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com