This is similar to the question, but a more specific case. This time, no compiler work as expected.
template<class T>
struct nondeduced
{
using type = T;
};
template<class T>
using nondeduced_t = typename nondeduced<T>::type;
template<class... T, class U>
void f(void(*)(nondeduced_t<T>..., U)) {}
void g(int, char) { }
int main()
{
f<int>(g); // error?
}
In the above example, the parameter pack T
cannot be deduced, but the compiler should be able to deduce U
after explicit arguments substitution for pack T
(i.e. single int
in this case).
The above is expected to work without the nondeduced_t
trick as well:
template<class... T, class U>
void f(void(*)(T..., U)) {}
Because the parameter pack T
is already in non-deduced context according to
[temp.deduct.type]p5
The non-deduced contexts are:
- A function parameter pack that does not occur at the end of the parameter-declaration-list.
Unfortunately, no compiler I tested (g++/clang) accept the code. Notably something like below works on both g++ & clang.
template<class... T>
void f(void(*)(nondeduced_t<T>..., char)) {}
And again, this doesn't work on both:
template<class... T>
void f(void(*)(T..., char)) {}
Is my expectation wrong?
template<class... T, class U> void f(void(*)(nondeduced_t<T>..., U)) {}
was ill-formed because a variadic parameter pack is appearing first. – AndyGT...
should be greedy under the standard -- it should leave nothing forU
to consume, so there is no ambiguity. Right? – Yakk - Adam Nevraumont