jeudi 1 septembre 2016

Can outer parameter pack be expanded with inner parameter pack to be deduced?

Given overloaded functions f1:

void f1(int);
int f1(char);

And a class template X with member template f:

template<class T>
struct X
{
    template<class U>
    static void f(T(*p)(U));
};

The compiler is able to resolve f1 from part of the function type:

X<int>::f(f1); // T = int (specified), U = char (deduced)
X<void>::f(f1); // T = void (specified), U = int (deduced)

However, a variadic class template Y with parameter pack at both sides:

template<class... T>
struct Y
{
    template<class... U>
    static void f(T(*...p)(U));
};

Fail to do the same thing:

Y<int>::f(f1); // error
Y<void>::f(f1); // error
Y<int, void>::f(f1, f1); // error

Note that it's OK if the parameter pack is only at one side:

template<class... T>
struct Z1
{
    template<class U>
    static void f(T(*...p)(U));
};

template<class T>
struct Z2
{
    template<class... U>
    static void f(T(*...p)(U));
};

Z1<int>::f(f1); // ok
Z2<void>::f(f1); // ok

This showns a problem: the outer parameter pack T cannot be expanded while the inner parameter pack U is still dependant. I imagine the compiler could expand Y::f to something like below when Y<int, void> is instantiated:

template<class... U>
void f(int(*p0)(U0), void(*p1)(U1));

where U0 and U1 denote the first 2 elements of parameter pack U.

But it seems that compilers(g++/clang) refuse to do so and leave the whole p unexpended. where in the standard does it specify such a behavior? Could it be a standard defect or something to improve?

Aucun commentaire:

Enregistrer un commentaire