Frans Bstrom
Frans Bstrom

Reputation: 305

Expand a tuple TYPE into a variadic template?

I have a function main_func where I modify the paramater pack/variadic template by converting it to a tuple. After I have modified it, ex: original = tuple<int, float, string> becomes modified = tuple<int float> I want to expand the modified tuple to another function in the example get_type_vectorso that the parameter pack represents the types of the modified tuple Args = int, float.

template<typename... Args>
void main_func()
{
    // Modify the parameter pack (which if im correct can only be done by converting to tuple?)
    using original = std::tuple<Args...>;
    using modified = // something that alters the types of the original tuple

    // This is what i want to accomplish
    // somehow expand the tuple type like a parameter pack
    auto vec = get_type_vector<modified...>()
}

// Returns a vector of type_info
template<typename... Args>
std::vector<type_info> get_type_vector()
{
    return { type_info<Args>()... };
}

Is it possible to somehow expand a tuple type like the type of a parameter pack? I have found examples using std::apply etc. but that requires you to have a value and not just the typedef of a tuple.

Upvotes: 1

Views: 1625

Answers (2)

A fairly simple approach would be to just overload and let the compiler deduce the types. std::type_identity can be useful here (C++20, but easily reproduced in any version of C++). It can create simple cheap tags out of types

template<typename... Args>
std::vector<type_info> get_type_vector(std::type_identity<std::tuple<Args...>>)
{
    return { type_info<Args>()... };
}

To use it is to write

auto vec = get_type_vector(std::type_identity<modified>{})

Upvotes: 2

Vittorio Romeo
Vittorio Romeo

Reputation: 93274

You can expand a tuple easily by introducing a layer of indirection, which could be a lambda (C++20) or template function (C++11). E.g.

std::tuple<int, float, char> t;
[]<typename... Ts>(std::tuple<Ts...>)
{
    // use `Ts...` here
}(t);

In your case:

template <typename T>
struct type_wrapper { using type = T; };

template<typename... Args>
std::vector<type_info> get_type_vector(type_wrapper<std::tuple<Args...>>)
{
    return { type_info<Args>()... };
}

get_type_vector(type_wrapper<std::tuple<int, float, char>>{});

The type_wrapper class prevents useless instantiations of tuples at run-time. You can use std::type_identity in C++20.

Upvotes: 4

Related Questions