c++ - 以自然(非反向)顺序将函数应用于 std::tuple 中的元素

标签 c++ c++11 functional-programming stdtuple

我需要为任意元组中的每个元素调用模板或重载函数。准确地说,我需要在元组中指定的元素上调用此函数。

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

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

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

1; 2.0f; 

而不是 2.0f; 1; .

请注意,如果将“原始”参数包传递给函数,我知道解决方案,并且我知道如何以相反的顺序为元组执行此操作。但是以下部分特化的尝试 Apply失败:

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特化

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

它工作正常 - 但是,当然,仅适用于长度为 2 的元组。我如何做到这一点 - 如果可能的话,优雅地 - 对于任意长度的元组?

编辑:谢谢你们的回答!这三者都非常直截了当,并从所有可能的有利角度解释了问题。

最佳答案

这是integer_sequence技巧的教科书案例。

template<class Func, class Tuple, size_t...Is>
void for_each_in_tuple(Func f, Tuple&& tuple, std::index_sequence<Is...>){
    using expander = int[];
    (void)expander { 0, ((void)f(std::get<Is>(std::forward<Tuple>(tuple))), 0)... };
}

template<class Func, class Tuple>
void for_each_in_tuple(Func f, Tuple&& tuple){
    for_each_in_tuple(f, std::forward<Tuple>(tuple),
               std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>());
}

Demo .

std::index_sequence 和 friend 是 C++14,但它是一个纯库扩展,可以很容易地在 C++11 中实现。您可以轻松地在 SO 上找到六个实现。

关于c++ - 以自然(非反向)顺序将函数应用于 std::tuple 中的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28343591/

相关文章:

c++ - 来自映射文件的 IO 与使用文件流的 IO

C++ MSXML2 - 从 XML 中删除 namespace

c++ - 如何使用 Linux 中的套接字层在 C++ 上编写 .wav 文件?

c++ - 根据另一个可变参数包查找可变参数包的收缩

scala - 使用无标签最终更改为错误的优雅方式

javascript - 使用 Ramda 递归 "merge"或 "extend"?

c++ - 没有顶点缓冲漫反射的着色纹理

c++ - 跨线程的unique_lock?

c++ - 编写更通用的指针代码

haskell - 什么是 "Scrap Your Boilerplate"?