Why won't template parameter pack be deduced to multiple type arguments in function call?

前端 未结 2 630
小鲜肉
小鲜肉 2021-02-12 16:29

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

2条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-02-12 16:53

    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.

提交回复
热议问题