Search code examples
c++variadic-templates

add two variadic template list of integers


Given this type

template<std::size_t N, int ...content>
struct list {
    inline int reduce() {
        int result = 0;
        constexpr int arr[N] = { content... };
        for(std::size_t k = 0; k < N; ++k) {
            result += arr[k];
        }

        return result;
    }
};

I'd like to implement a function add, which returns a new list containing the element-by-element addition of the two input lists. In other words (pseudo-code):

add([a0, a1, a2], [b0, b1]) -> [a0 + b0, a1 + b2, a2]

Problem:

  • I don't even know how to declare the return type of such a function
  • and i don't know if it's possible

Solution

  • Here is how I would do it:

    #include <iostream>
    #include <utility>
    
    template<std::size_t N, int ...content>
    struct list {
        inline int reduce() {
            int result = 0;
            constexpr int arr[N] = { content... };
            for(std::size_t k = 0; k < N; ++k) {
                result += arr[k];
            }
    
            return result;
        }
    };
    
    
    template <std::size_t I, int ...A>
    constexpr int list_at(list<sizeof...(A),A...>)
    {
        if constexpr (I < sizeof...(A))
        {
            constexpr int arr[] {A...};
            return arr[I];
        }
        else
        {
            return 0;
        }
    }
    
    template <int ...A, int ...B, std::size_t ...I>
    constexpr auto list_sum_low(list<sizeof...(A),A...>,
                                list<sizeof...(B),B...>,
                                std::index_sequence<I...>)
    {
        return list<sizeof...(I), (list_at<I>(list<sizeof...(A),A...>{}) +
                                   list_at<I>(list<sizeof...(B),B...>{}))...>{};
    }
    
    template <int ...A, int ...B>
    constexpr auto list_sum(list<sizeof...(A),A...>, list<sizeof...(B),B...>)
    {
        constexpr int a = sizeof...(A), b = sizeof...(B);
        return list_sum_low(list<a,A...>{}, list<b,B...>{},
                            std::make_index_sequence<(a > b ? a : b)>{});
    }
    
    
    template <int ...A>
    void print_list(list<sizeof...(A),A...>)
    {
        (void(std::cout << ' ' << A) , ...);
    }
    
    
    int main()
    {
        constexpr auto x = list_sum(list<4, 1,2,3,4>{}, list<2, 10,20>{});
        print_list(x);
    }
    

    Also, note that there is no need have size_t N template parameter for class list. Parameter packs know their own size.