忽略缺少的完美转发。 (假设参数在实际执行完美转发。)获取第n个可变参数值(不是类型)
// Base case: no args
template<typename TF> void forEach2Args(TF) { }
// Recursive case: some args
template<typename TF, typename... Ts> void forEach2Args(TF mFn, Ts... mXs)
{
mFn(getNth<0>(mXs...), getNth<1>(mXs...));
forEach2Args(mFn, getAllAfter<2>(mXs...));
}
int main()
{
int result{0};
forEach2Args([&result](auto a1, auto a2)
{
result += (a1 * a2);
}, 2, 4, 3, 6);
// roughly evaluates to:
// result += (2 * 4);
// result += (3 * 6);
}
是否有可能实现getNth
和getAllAfter
避免任何可能的运行时开销?到目前为止,我发现的唯一解决方案是将第一个forEach2Args
调用中的每个Ts...
放在std::tuple
的内部,然后将每个递归调用的非常量引用传递给该元组。我几乎可以确定有不必要的移动/ ctor/dtor调用。
另一种解决方案是使用这样的:
// Base case: no args
template<typename TF> void forEach2Args(TF) { }
// Recursive case: some args
template<typename TF, typename T1, typename T2, typename... Ts>
void forEach2Args(TF mFn, T1 mX1, T2 mX2, Ts... mXs)
{
mFn(mX1, mX2);
forEach2Args(mFn, mXs...);
}
但是这种解决方案需要,如果我想通过在3个而不是2,或任何其他数量的组参数,再次实现。我想要一些动态的地方,我可以指定通过模板参数传递给每个mFn
调用的参数数量。喜欢的东西:
forEachNArgs<3>([](auto a1, auto a2, auto a3){ /*...*/ }, /*...*/);
forEachNArgs<4>([](auto a1, auto a2, auto a3, auto a4){ /*...*/ }, /*...*/);
使用'的std :: tie'有不复制其参数的元组。 –
@DanielFrey:看起来'std :: tie'带有l值引用。如果我在'mFn'调用期间传递给'forEach2Args'的r值引用,它会阻止正确的转发吗? –
@VittorioRomeo,看来正确的方法是'std :: forward_as_tuple(std :: forward(values)...)' –
chris