Search code examples
c++tuplesvariadic-templatestemplate-meta-programming

How to write a function with an arbitrary number of parameter packs


I was trying to implement some generic functions for my protocol working over UDP sockets for game engines (for learning purposes), when I have stumpled upon a need to have a function that must accept arbitrary number of tuples, every one of which might have their own number of different parameters. Example of usage:

int main() {
   ...
   socket.form_packet(std::tuple{"Hello", 1}, std::tuple{3.1415, var, 'g'});
}

I've tried this approach:

template<typename ...Values>
void form_packet(const std::tuple<Values...>& tuple)
{
    handle_single_tuple(tuple);
}

template<template<typename ...> typename ...Tuple, typename ...Values>
void form_packet(const std::tuple<Values...>& tuple, const Tuple<Values...>&... tuples)
{
    handle_single_tuple(tuple);
    form_packet(tuples...);
}

But this kind of implementation supports only arbitrary number of tuples, where each one can have the same types (Values...) of its members.
I wonder if what I want to do is possible to be done in C++. If yes, what needs to be improved in my code mentioned above?

Thanks in advance.


Solution

  • Using this type trait to check if a type is a specialization of a template

    template <class T, template <class...> class Template>
    struct is_specialization : std::false_type {};
    
    template <template <class...> class Template, class... Args>
    struct is_specialization<Template<Args...>, Template> : std::true_type {};
    

    You can change your function to just a normal variadic template, but add SFINAE to constrain the generic type to only being specializations of std::tuple like

    template <typename... Tuples, 
              std::enable_if_t<(is_specialization<Tuples, std::tuple>::value && ...), bool> = true>
    void form_packet(const Tuples...& tuples)
    {
        (handle_single_tuple(tuples), ...); // comma operator used to call each member in order
    }