I have a class templated on a type parameter and parameter pack, and am confused about type-deduction of this type; while writing an output-streaming operator I discovered a par
What is happening is that a template function with a template parameter pack class... Ts, and a parameter type (P) of foo is being deduced against an argument type (A) of foo.
14.8.2.5/9 says of this:
If P has a form that contains
or[it does], then each argument Pi [Ts...] of the respective template argument list P is compared with the corresponding argument Ai [int] of the corresponding template argument list of A. If the template argument list of P contains a pack expansion that is not the last template argument, the entire template argument list is a non-deduced context. [the pack expansion is last, so the previous doesnt apply] If Pi is a pack expansion [Ts..., it is], then the pattern of Pi is compared with each remaining argument in the template argument list of A (int). Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by Pi.
So class... Ts should be deduced as the one element list int, and consequently the function template should be instantiated with the parameter type const foo, and be viable.
It is a compiler bug. Your code is well-formed.
More succinctly this is well-formed:
template struct S { };
template void f(S) { }
int main() { f(S()); }
but fails similarly on at least gcc 4.7.2 with:
error: parameter 1 of ‘void f(S) [with C = {int, C}]’
has incomplete type ‘S’
C is incorrectly deduced as C = {int, C} (a nonsensical recursion) instead of C = {int}. The broken deduction of C leads to further garbage that S has an incomplete type.