Search code examples
c++c++17variadic-templatesvariadic-functions

Variadic template returning a N-tuple based on an unknown number of arguments


I would like to have a variadic function template that takes pointers of a certain type T, fills those pointers, and for each of them generate an object as a result, the final result being a tuple of all these generated objects.

Given a function from a library (that uses a C api):

struct opaque {};

bool fill_pointer(opaque **);

And:

struct MyType {};

MyType gen_object(opaque *);

I would like to have a variadic template function that would look like this (sort of):

std::tuple<bool, MyType...> fill_and_gen_objects(opaque **...);

(where the bool result is false if and only one of fill_pointer return value is false).

This is what I would like to achieve:

opaque *oa, *ob, *oc;
auto [failed, ta, tb, tc] = fill_and_gen_objects(oa, ob, oc);

Thanks


Solution

  • That's heavy pseudocode, I'll answer with heavy pseudocode:

    template<typename ... Ts>
    constexpr auto fill_and_gen_objects(Ts* ... os)
    { 
        bool some_status = true; //whatever
        return std::make_tuple(some_status, gen_object(os) ...);
    }
    

    Ok, actually it even compiles, see here

    EDIT: downgraded to C++14 ... that's what you've tagged.


    Same for C++17 using CTAD

    template<typename ... Ts>
    constexpr auto fill_and_gen_objects(Ts* ... os)
    { 
        bool some_status = true; //whatever
        return std::tuple{some_status, gen_object(os) ...};
    }
    

    Same for C++20 using abbreviated function template syntax

    constexpr auto fill_and_gen_objects(auto* ... os)
    { 
        bool some_status = true; //whatever
        return std::tuple{some_status, gen_object(os) ...};
    }
    

    C++20 with indices by using integer sequence (untested):

    constexpr auto fill_and_gen_objects(auto* ... os)
    { 
        bool some_status = true; //whatever
        return []<int ... I>(std::index_sequence<I...>, auto tup){ return std::tuple{some_status, gen_object(std::get<I>(tup)) ...};}
        (std::make_index_sequence<sizeof...(os)>{}, std::tuple{os...})
    }
    

    Furthermore, here is the C++27 solution:

    void do_my_fckng_work() { bool asap = true; }