Search code examples
c++templatesc++17variadic-templatesnon-type

Cross multiply non-type variadic templates


My goal is to make this template work:

template <size_t... Ns>
struct mult
{
    using cross = ?; // variadic size_t
    static_assert(sizeof...(cross) + 1 == sizeof...(Ns), "");
};

So I can use it like this:

mult<2,3,5>::cross // 6,15 // because 2*3=6, 3*5=15
mult<3,5,7,11>::cross // 15,35,77 // because 3*5=15, 5*7=35, 7*11=77

Because I need to make this:

// tuple of arrays
std::tuple<std::array<size_t, mult<Ns...>::cross>...> cross_arrays;

Solution

  • If you want compile time computation, write constexpr functions

    template<typename... SizeT>
    constexpr auto cross(size_t x, SizeT... xs)
    {
        std::array tmp = {x, xs...};
        std::array ret = {xs...};
        for(size_t i = 0; i < ret.size(); i++)
            ret[i] *= tmp[i];
        return ret;
    }
    
    template<size_t... xs, size_t... Is>
    auto cross_tuple_fn(std::index_sequence<Is...>)
    {
        constexpr auto dims = cross(xs...);
        return std::tuple<std::array<size_t, dims[Is]>...>{};
    }
    
    template<size_t... xs>
    auto cross_tuple_fn()
    {
        return cross_tuple_fn<xs...>(std::make_index_sequence<sizeof...(xs) - 1>{});
    }
    
    template<size_t... xs>
    using cross_tuple_t = decltype(cross_tuple_fn<xs...>());
    

    They're easier to read, write and looks more or less the same as normal functions.

    Use as

    cross_tuple_t<Ns...> cross_arrays;