获得第n个可变参数的参数值(不是类型) [英] Getting nth variadic argument value (not type)

查看:133
本文介绍了获得第n个可变参数的参数值(不是类型)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

忽略缺失的完美转​​发。的(假设参数在真正的实现完美转发​​。)

  //基本情况:无参数
模板< 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... ) );
}

Live example

这篇关于获得第n个可变参数的参数值(不是类型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆