我真的很高兴发现for_each_arg(...) https://twitter.com/ericniebler/status/559119062895431680,这使得处理参数包变得更加容易。
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;
}
我所有的问题/疑问都在上面代码示例的注释中表达了。
Every 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)) );
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)