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

查看:23
本文介绍了获取第 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);
}

是否可以实现 getNthgetAllAfter 以避免任何可能的运行时开销?到目前为止,我发现的唯一解决方案是将每个 Ts... 放在 std::tuple 中的第一个 forEach2Args 调用和然后将对该元组的非常量引用传递给每个递归调用.我几乎可以肯定有不必要的 move/ctor/dtor 调用.

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...);
}

但是如果我想以 3 组而不是 2 组或任何其他数字为一组传递参数,则需要再次实施此解决方案.我想要一些动态的东西,我可以通过模板参数指定要传递给每个 mFn 调用的参数数量.类似的东西:

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屋!

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