对std :: tuple中的元素应用func以自然(不反向)顺序 [英] Applying func to elements in std::tuple in the natural (not reverse) order

查看:137
本文介绍了对std :: tuple中的元素应用func以自然(不反向)顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要为任意元组中的每个元素调用一个 - 模板或重载的函数。确切地说,我需要在元素上调用这个函数,因为它们在元组中指定。

I need to call a - template or overloaded - function for each element in an arbitrary tuple. To be precise, I need to call this function on the elements as they are specified in the tuple.

例如。我有一个元组 std :: tuple< int,float> t {1,2.0f}; 和功能

For example. I have a tuple std::tuple<int, float> t{1, 2.0f}; and a functional

class Lambda{
public: 
   template<class T>
   void operator()(T arg){ std::cout << arg << "; "; }
};



我需要一些结构/函数 Apply 如果调用 Apply< Lambda,int,float>()(Lambda(),t)会产生:

1; 2.0f; 

和NOT 2.0f; 1;

注意,我知道解决方案,如果一个raw参数包被传递到函数,对于元组以相反的顺序。但下面尝试部分专门化 Apply 失败:

Note that I know the solution, if a "raw" parameter pack is passed in to the function and I know how to do that for tuples in the reverse order. But the following attempt of partially specializing Apply fails:

template<class Func, size_t index, class ...Components>
class ForwardsApplicator{
public:
    void operator()(Func func, const std::tuple<Components...>& t){
        func(std::get<index>(t));
        ForwardsApplicator<Func, index + 1, Components...>()(func, t);
    }
};

template<class Func, class... Components>
class ForwardsApplicator < Func, sizeof...(Components), Components... > {
public:
    void operator()(Func func, const std::tuple<Components...>& t){}
};

int main{
    ForwardsApplicator<Lambda, 0, int, float>()(Lambda{}, std::make_tuple(1, 2.0f));
}

代码已编译,但只打印第一个参数。但是,如果我将 ForwardsApplicator 替换为

The code is compiled but only the first argument is printed. However, if I replace the ForwardsApplicator specialization with

template<class Func, class... Components>
class ForwardsApplicator < Func, 2, Components... >{...}

当然,只有对于长度为2的元组。我如何做 - 如果可能,优雅 - 对任意长度的元组?

it works correctly - but, of course, only for tuples with length 2. How do I do that - if possible, elegantly -- for tuples of arbitrary length?

编辑:感谢各位的回答!

Thanks guys for your answers! All three are really straight-to-the-point and explain the issue from all possible vantage points.

推荐答案

问题是,这个问题是, size ...(Components)不能用于未知类型列表的特殊化 Components 。 GCC抱怨出现错误:

The problem is that size...(Components) can not be used in the specialization for an unknown type list Components. GCC complains about this with the error:


prog.cpp:16:7: error: template argument 'sizeof... (Components)' involves template parameter(s)
 class ForwardsApplicator < Func, sizeof...(Components), Components... > {
       ^


我建议稍微不同的方法。首先,将类型列表 Components 移动到运算符()的模板参数,即:

I suggest a slightly different approach. First, move the type list Components into the template parameter for the operator(), i.e.:

template<class ...Components>
void operator()(Func func, const std::tuple<Components...>& t) {
    ...
}

然后,反转调用顺序:首先进行递归调用,然后调用 index-1 (即调用最后元组)。用 index = sizeof ...(Components)开始递归,直到 index = 0 ,这是noop专业化有 0 ,独立于 sizeof ...(Components)这是我开始讨论的问题)

Then, reverse the call order: first do a recursive call, then the invokation with index-1 (i.e. call on the last tuple element). Start this recursion with index = sizeof...(Components) and go until index = 0 which is noop (so the specialization has 0, independent of sizeof...(Components) which was the problem I began to talk about).

要帮助调用此函数,请添加模板参数扣除函数:

To help call this, add a function for template argument deduction:

// General case (recursion)
template<class Func, size_t index>
class ForwardsApplicator{
public:
    template<class ...Components>
    void operator()(Func func, const std::tuple<Components...>& t){
        ForwardsApplicator<Func, index - 1>()(func, t);
        func(std::get<index - 1>(t));
    }
};

// Special case (stop recursion)
template<class Func>
class ForwardsApplicator<Func, 0> {
public:
    template<class ...Components>
    void operator()(Func func, const std::tuple<Components...>& t){}
};

// Helper function for template type deduction
template<class Func, class ...Components>
void apply(Func func, const std::tuple<Components...>& t) {
    ForwardsApplicator<Func, sizeof...(Components)>()(func, t);
}

然后很容易调用,而不需要任何模板参数调用网站:

It is then easy to invoke, without the need for any template parameters on the call site:

apply(Lambda{}, std::make_tuple(1, 2.0f));

现场演示

这篇关于对std :: tuple中的元素应用func以自然(不反向)顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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