lightxbulb
lightxbulb

Reputation: 1321

Using parameter pack as typename for a templated class

Is this valid: https://godbolt.org/z/_i9dwf

#include <typeinfo>
#include <iostream>

template<typename T>
struct Container
{
};

void fn()
{
    return;
}

template<typename T, typename...type_pack>
void fn(const Container<T>& head, const Container<type_pack>&... args)
{
    std::cout << "I am an " << typeid(T).name() << "\n";
    fn(args...);
    return;
}

int main()
{
    fn(Container<int>{}, Container<float>{});
    return 0;
}

Does C++ actually allow such expansions, or is this implementation defined based on compiler? I don't believe I have seen this type of syntax used elsewhere: Container<type_pack>&.... It's just something I came up with for what I wanted to achieve, and surprisingly it works. So my question is, is this UB, or is there an actual mention in the standard that this is well-defined?

Upvotes: 1

Views: 44

Answers (2)

Fureeish
Fureeish

Reputation: 13444

You are specifying a variable number of arguments, which are of a type Container, templated with types that will be used for deducing type_pack. For example, if you call:

fn(Container<int>{}, Container<float>{});

The type_pack will represent a float type. However, if you call:

fn(Container<int>{}, Container<float>{}, Container<int>{}, Container<std::string>{});

The type_pack will represent a parameter pack of float, int, std::string.

This behaviour is well defined by the standard.

Upvotes: 2

max66
max66

Reputation: 66230

Why not?

In your code, type_pack

template<typename T, typename...type_pack>
void fn(const Container<T>& head, const Container<type_pack>&... args)

is in deduced context, so the compiler can deduce float, for type_pack..., from

fn(Container<int>{}, Container<float>{});

Upvotes: 2

Related Questions