Sum the components of a tuple up by using std::get, std::tuple_size, std::tuple_element

前端 未结 2 1473
深忆病人
深忆病人 2021-01-06 04:45

I\'ve got a custom class that has a tuple-like interface. Because I want my code to be as generic as possible, I thought that it would be a good idea to base my algorithms o

2条回答
  •  北海茫月
    2021-01-06 05:23

    With C++1z it's pretty simple with fold expressions. First, forward the tuple to an _impl function and provide it with index sequence to access all tuple elements, then sum:

    template
    auto sum_components_impl(T const& t, std::index_sequence)
    {
        return (std::get(t) + ...);
    }
    
    template 
    int sum_components(const Tuple& t)
    {
        constexpr auto size = std::tuple_size{};
        return sum_components_impl(t, std::make_index_sequence{});
    }
    

    demo


    A C++14 approach would be to recursively sum a variadic pack:

    int sum()
    {
        return 0;
    }
    
    template
    auto sum(T&& t, Us&&... us)
    {
        return std::forward(t) + sum(std::forward(us)...);
    }
    
    template
    auto sum_components_impl(T const& t, std::index_sequence)
    {
        return sum(std::get(t)...);
    }
    
    template 
    int sum_components(const Tuple& t)
    {
        constexpr auto size = std::tuple_size{};
        return sum_components_impl(t, std::make_index_sequence{});
    }
    

    demo

    A C++11 approach would be the C++14 approach with custom implementation of index_sequence. For example from here.


    As @ildjarn pointed out in the comments, the above examples are both employing right folds, while many programmers expect left folds in their code. The C++1z version is trivially changeable:

    template
    auto sum_components_impl(T const& t, std::index_sequence)
    {
        return (... + std::get(t));
    }
    

    demo

    And the C++14 isn't much worse, but there are more changes:

    template
    auto sum(T&& t, Us&&... us)
    {
        return sum(std::forward(us)...) + std::forward(t);
    }
    
    template
    auto sum_components_impl(T const& t, std::index_sequence)
    {
        constexpr auto last_index = sizeof...(Is) - 1;
        return sum(std::get(t)...);
    }
    

    demo

提交回复
热议问题