Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::views like operation on parameters pack

I need sometimes to filter some types from a given parameter pack and get the result as a std::tuple. For instance, it can be a filter based on the index of the types in the pack.

As an example, here is a recursive implementation of a stride-like filter, with a semantic similar to std::views::stride

#include <tuple>

namespace pack
{
    template<int R, int IDX, typename...ARGS>
    struct stride_impl  { };

    template<int R, int IDX, typename...ARGS>
    using stride_impl_t = typename stride_impl<R,IDX,ARGS...>::type;

    template<int R, int IDX, typename T, typename...ARGS>
    struct stride_impl<R,IDX,T,ARGS...>
    {
        using type = std::conditional_t <
            IDX%R==0,
            decltype(std::tuple_cat (
                std::tuple<T> {}, 
                stride_impl_t<R,IDX+1,ARGS...> {} 
            )),
            stride_impl_t<R,IDX+1,ARGS...>
        >;     
    };

    template<int R, int IDX>
    struct stride_impl<R,IDX>  {  using type = std::tuple<>;  };

    template<int R, typename...ARGS>
    struct stride 
    {  
        static_assert(R>0);
        using type = stride_impl_t<R,0,ARGS...>;
    };

    template<int R, typename ...ARGS>
    using stride_t = typename stride<R,ARGS...>::type;
};

template<int R> using example = pack::stride_t<R,char,int,long,float,double>;

static_assert (std::is_same_v< example<1>, std::tuple<char,int,long,float,double>>);
static_assert (std::is_same_v< example<2>, std::tuple<char,    long,      double>>);
static_assert (std::is_same_v< example<3>, std::tuple<char,         float       >>);
static_assert (std::is_same_v< example<4>, std::tuple<char,               double>>);
static_assert (std::is_same_v< example<5>, std::tuple<char                      >>);

int main() {}

which feels tedious.

Is it possible to have a more direct implementation that avoids explicit recursion (maybe with fold expression)? Perhaps there is something in std that covers such filters on parameters packs in a similar way to std::views?

like image 213
abcdefg Avatar asked Sep 03 '25 14:09

abcdefg


1 Answers

With std::index_sequence, you might do

namespace pack
{

    template<int R, typename...ARGS>
    struct stride 
    {  
        static_assert(R>0);
        using type = decltype([]<std::size_t... Is>(std::index_sequence<Is...>) ->
            std::tuple<std::tuple_element_t<Is * R, std::tuple<ARGS...>>...>
        {
            throw 42;
        }(std::make_index_sequence<std::min(sizeof...(ARGS), 1 + (sizeof...(ARGS) - 1) / R)>()));
    };

    template<int R, typename ...ARGS>
    using stride_t = typename stride<R,ARGS...>::type;
};

Demo

like image 179
Jarod42 Avatar answered Sep 05 '25 02:09

Jarod42