Template tuple - calling a function on each element

后端 未结 7 2105
猫巷女王i
猫巷女王i 2020-11-27 02:28

My question is in the code:

template
struct TupleOfVectors {
  std::tuple...> tuple;

  void do_something_t         


        
7条回答
  •  旧巷少年郎
    2020-11-27 03:22

    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
        struct seq { };
    
        template
        struct gen_seq : gen_seq { };
    
        template
        struct gen_seq<0, Is...> : seq { };
    }
    

    And the following function templates:

    #include 
    
    namespace detail
    {
        template
        void for_each(T&& t, F f, seq)
        {
            auto l = { (f(std::get(t)), 0)... };
        }
    }
    
    template
    void for_each_in_tuple(std::tuple const& t, F f)
    {
        detail::for_each(t, f, detail::gen_seq());
    }
    

    You can use the for_each_in_tuple function above this way:

    #include 
    #include 
    
    struct my_functor
    {
        template
        void operator () (T&& t)
        {
            std::cout << t << std::endl;
        }
    };
    
    int main()
    {
        std::tuple 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
    struct TupleOfVectors
    {
        std::tuple...> t;
    
        void do_something_to_each_vec()
        {
            for_each_in_tuple(t, tuple_vector_functor());
        }
    
        struct tuple_vector_functor
        {
            template
            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
        void
        for_each(T&& t, F f, std::integer_sequence)
        {
            auto l = { (f(std::get(t)), 0)... };
        }
    } // namespace detail
    
    template
    void
    for_each_in_tuple(std::tuple const& t, F f)
    {
        detail::for_each(t, f, std::make_integer_sequence());
    }
    

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

提交回复
热议问题