模板元组 - 在每个元素上调用一个函数

时间:2023-03-10
本文介绍了模板元组 - 在每个元素上调用一个函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我的问题在代码中:

templatestruct TupleOfVectors {std::tuple<std::vector<Ts>...>元组;void do_something_to_each_vec() {//问题:我想这样做://"for each (N)": do_something_to_vec()//如何?}模板void do_something_to_vec() {auto &vec = std::get(tuple);//对 vec 做一些事情}};

解决方案

您可以使用一些索引机制轻松地做到这一点.给定一个元函数 gen_seq 用于生成编译时整数序列(由 seq 类模板封装):

命名空间细节{模板结构序列{};templatestruct gen_seq : gen_seq{ };模板struct gen_seq<0, Is...>: seq<是...>{ };}

以及以下函数模板:

#include <元组>命名空间细节{templatevoid for_each(T&& t, F f, seq){auto l = { (f(std::get(t)), 0)... };}}templatevoid for_each_in_tuple(std::tuple<Ts...>const&t, F f){detail::for_each(t, f, detail::gen_seq());}

你可以这样使用上面的for_each_in_tuple函数:

#include #include struct my_functor{模板void 运算符 () (T&& t){std::cout <<t<<std::endl;}};int main(){std::tuplet(42, 3.14, "Hello World!");for_each_in_tuple(t, my_functor());}

这是一个现场示例.>

在您的具体情况下,您可以这样使用它:

templatestruct TupleOfVectors{std::tuple<std::vector<Ts>...>t;void do_something_to_each_vec(){for_each_in_tuple(t, tuple_vector_functor());}struct tuple_vector_functor{模板void 运算符 () (T const &v){//对参数向量做一些事情...}};};

再一次,这是一个现场示例.

更新

如果您使用的是 C++14 或更高版本,则可以将上面的 seqgen_seq 类替换为 std::integer_sequence 像这样:

命名空间细节{template空白for_each(T&&t, F f, std::integer_sequence){auto l = { (f(std::get(t)), 0)... };}}//命名空间细节template空白for_each_in_tuple(std::tuple<Ts...>const&t, F f){detail::for_each(t, f, std::make_integer_sequence());}

如果您使用的是 C++17 或更高版本,则可以执行此操作(来自 下面的此评论):

std::apply([](auto ...x){std::make_tuple(some_function(x)...);} , the_tuple);

My question is in the code:

template<typename... Ts>
struct TupleOfVectors {
  std::tuple<std::vector<Ts>...> tuple;

  void do_something_to_each_vec() {
    //Question: I want to do this:
    //  "for each (N)": do_something_to_vec<N>()
    //How?
  }

  template<size_t N>
  void do_something_to_vec() {
    auto &vec = std::get<N>(tuple);
    //do something to vec
  }
};

解决方案

You can quite easily do that with some indices machinery. Given a meta-function gen_seq for generating compile-time integer sequences (encapsulated by the seq class template):

namespace detail
{
    template<int... Is>
    struct seq { };

    template<int N, int... Is>
    struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };

    template<int... Is>
    struct gen_seq<0, Is...> : seq<Is...> { };
}

And the following function templates:

#include <tuple>

namespace detail
{
    template<typename T, typename F, int... Is>
    void for_each(T&& t, F f, seq<Is...>)
    {
        auto l = { (f(std::get<Is>(t)), 0)... };
    }
}

template<typename... Ts, typename F>
void for_each_in_tuple(std::tuple<Ts...> const& t, F f)
{
    detail::for_each(t, f, detail::gen_seq<sizeof...(Ts)>());
}

You can use the for_each_in_tuple function above this way:

#include <string>
#include <iostream>

struct my_functor
{
    template<typename T>
    void operator () (T&& t)
    {
        std::cout << t << std::endl;
    }
};

int main()
{
    std::tuple<int, double, std::string> t(42, 3.14, "Hello World!");
    for_each_in_tuple(t, my_functor());
}

Here is a live example.

In your concrete situation, this is how you could use it:

template<typename... Ts>
struct TupleOfVectors
{
    std::tuple<std::vector<Ts>...> t;

    void do_something_to_each_vec()
    {
        for_each_in_tuple(t, tuple_vector_functor());
    }

    struct tuple_vector_functor
    {
        template<typename T>
        void operator () (T const &v)
        {
            // Do something on the argument vector...
        }
    };
};

And once again, here is a live example.

Update

If you're using C++14 or later, you can replace the seq and gen_seq classes above with std::integer_sequence like so:

namespace detail
{
    template<typename T, typename F, int... Is>
    void
    for_each(T&& t, F f, std::integer_sequence<int, Is...>)
    {
        auto l = { (f(std::get<Is>(t)), 0)... };
    }
} // namespace detail

template<typename... Ts, typename F>
void
for_each_in_tuple(std::tuple<Ts...> const& t, F f)
{
    detail::for_each(t, f, std::make_integer_sequence<int, sizeof...(Ts)>());
}

If you're using C++17 or later you can do this (from this comment below):

std::apply([](auto ...x){std::make_tuple(some_function(x)...);} , the_tuple);

这篇关于模板元组 - 在每个元素上调用一个函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:带有包扩展的可变函数模板不在最后一个参数中 下一篇:当我们有模板模板参数时,为什么需要 allocator::rebind ?

相关文章