获得第n个可变参数的参数值(不是类型) [英] Getting nth variadic argument value (not type)
问题描述
忽略缺失的完美转发。的(假设参数在真正的实现完美转发。)的
//基本情况:无参数
模板< typename的TF>空隙forEach2Args(TF){}//递归情况:一些ARGS
模板< typename的TF,类型名称... TS>无效forEach2Args(TF最惠国待遇,TS ... MXS)
{
MFN(getNth&℃,GT(MXS ...),getNth&所述1为卤素;(MXS ...));
forEach2Args(MFN,getAllAfter 2>(MXS ...));
}诠释的main()
{
INT结果{0};
forEach2Args([安培;结果](自动A1,A2汽车)
{
结果+ =(A1 * A2);
},2,4,3,6); //粗略计算为:
//结果+ =(2 * 4);
//结果+ =(3 * 6);
}
是否有可能实施 getNth
和 getAllAfter
避免任何可能的运行时开销?到目前为止,我已经找到了唯一的解决办法是把每个 TS ...
的内部的std ::元组
上第一个 forEach2Args
调用,然后传递非const引用到元组的每一个递归调用。我几乎可以肯定有多此一举/构造函数/析构函数调用虽然。
另一种解决方案是使用这样的:
//基本情况:无参数
模板< typename的TF>空隙forEach2Args(TF){}//递归情况:一些ARGS
模板< typename的TF,typename的T1,T2类型名称,类型名称... TS>
无效forEach2Args(TF最惠国待遇,MX1 T1,T2 MX2,TS ... MXS)
{
MFN(MX1,MX2);
forEach2Args(MFN,MXS ...);
}
但是这种解决方案需要,如果我想通过在3而不是2,或任何其他数量的组参数被再次执行。我想要的东西的动态,我可以指定多少参数传递给每一个最惠国
通过模板参数调用。是这样的:
forEachNArgs 3;>([](自动A1,A2自动,自动A3){} /*...*/,/*...*/);
forEachNArgs&所述4是氢;([](自动A1,自动A2,自动A3,自动A4){/*...*/},/*...*/);
忽略了完美转发的要求,这应该工作:
模板< typename的B,typename的C>
结构forEachNArgsImpl;模板<的std ::为size_t ...旅馆,性病::为size_t ... CS>
结构forEachNArgsImpl<
的std :: index_sequence<烧烤...>中
的std :: index_sequence<铯...>
>
{
模板<的std ::为size_t N,typename的TF,类型名称... TS>
静态无效execN(TF最惠国待遇,常量的std ::元组LT; TS ...>&安培; MXS)
{
最惠国(性病::获得< N + CS>(MXS)...);
} 模板< typename的TF,类型名称... TS>
静态无效EXEC(TF最惠国待遇,常量的std ::元组LT; TS ...>&安培; MXS)
{
使用燕子=布尔[];
(无效){吞(execN<烧烤* sizeof的...(CS)>(MFN,MXS),真)...};
}
};模板<的std ::为size_t N,typename的TF,类型名称... TS>
无效forEachNArgs(TF最惠国待遇,TS ... MXS)
{
static_assert(...的sizeof(TS)%N == 0的参数个数错误);
forEachNArgsImpl<
的std :: make_index_sequence< ...的sizeof(TS)/ N>中
的std :: make_index_sequence< N>
> :: EXEC(MFN,性病:: forward_as_tuple(MXS ...));
}
Ignore the missing perfect forwarding. (Assume arguments are perfectly forwarded in the real implementation.)
// 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);
}
Is it possible to implement getNth
and getAllAfter
avoiding any possible runtime overhead? The only solution I've found so far is putting every Ts...
inside of an std::tuple
on the first forEach2Args
call and then passing a non-const reference to that tuple to every recursive call. I'm almost sure there are unnecessary move/ctor/dtor calls though.
Another solution is using something like:
// 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...);
}
But this solution needs to be implemented again if I want to pass parameters in groups of 3 instead of 2, or any other number. I wanted something dynamic where I can specify how many arguments to pass to every mFn
call through a template parameter. Something like:
forEachNArgs<3>([](auto a1, auto a2, auto a3){ /*...*/ }, /*...*/);
forEachNArgs<4>([](auto a1, auto a2, auto a3, auto a4){ /*...*/ }, /*...*/);
Ignoring the perfect forwarding as requested, this should work:
template<typename B, typename C>
struct forEachNArgsImpl;
template<std::size_t... Bs, std::size_t... Cs>
struct forEachNArgsImpl<
std::index_sequence<Bs...>,
std::index_sequence<Cs...>
>
{
template<std::size_t N, typename TF, typename... Ts>
static void execN(TF mFn, const std::tuple<Ts...>& mXs)
{
mFn( std::get< N + Cs >( mXs )... );
}
template<typename TF, typename... Ts>
static void exec(TF mFn, const std::tuple<Ts...>& mXs)
{
using swallow = bool[];
(void)swallow{ (execN< Bs * sizeof...(Cs) >( mFn, mXs ), true)... };
}
};
template<std::size_t N, typename TF, typename... Ts>
void forEachNArgs(TF mFn, Ts... mXs)
{
static_assert( sizeof...(Ts) % N == 0, "Wrong number of arguments" );
forEachNArgsImpl<
std::make_index_sequence<sizeof...(Ts)/N>,
std::make_index_sequence<N>
>::exec(mFn, std::forward_as_tuple( mXs... ) );
}
这篇关于获得第n个可变参数的参数值(不是类型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!