Parameter pack must be at the end of the parameter list… When and why?

后端 未结 2 601
猫巷女王i
猫巷女王i 2020-11-27 18:48

I don\'t get the reason for which a parameter pack must be at the end of the parameter list if the latter is bound to a class, while the constraint is relaxed if the paramet

相关标签:
2条回答
  • 2020-11-27 19:22

    The first one is not right. The compiler is just buggy and failed to diagnose it. [temp.param]/11:

    A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list of the function template or has a default argument (14.8.2).


    If the function type T(Args...) is meaningful to the end-user, one way to fix this would be to use a partial specialization instead:

    template<class F, class Alloc> class C; //undefined
    template<class T, class... Args, class Alloc>
    class C<T(Args...), Alloc> {
        // implementation
    };
    

    Depending on the actual requirements, type-erasing the allocator might also be worth considering.

    0 讨论(0)
  • 2020-11-27 19:30

    It is valid for function templates but only when argument deduction can help the compiler resolve the template parameters, as it stands your function template example is virtually useless because

    template<typename T, typename... Args, typename S> void fn() { }
    int main() { fn<int, int, int>(); }
    
    test.cpp: In function 'int main()':
    test.cpp:2:32: error: no matching function for call to 'fn()'
     int main() { fn<int, int, int>(); }
                                    ^
    test.cpp:1:57: note: candidate: template<class T, class ... Args, class S> void fn()
     template<typename T, typename... Args, typename S> void fn() { }
                                                             ^
    test.cpp:1:57: note:   template argument deduction/substitution failed:
    test.cpp:2:32: note:   couldn't deduce template parameter 'S'
     int main() { fn<int, int, int>(); }
    

    the compiler has no way of determining which template parameters belong to the parameter pack, and which to S. In fact as @T.C. points out it should actually be a syntax error because a function template defined in this manner cannot ever be instantiated.

    A more useful function template would be something like

    template<typename T, typename... Args, typename S> void fn(S s) { }
    

    as now the compiler is able to unambiguously match the function parameter s with the template type S, with the side effect that S will always be deduced - all explicit template parameters after the first will belong to Args.

    None of this works for (primary) class templates, parameters aren't deduced and it's expressly forbidden:

    From draft n4567

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4567.pdf

    [temp.param] / 11

    [...]If a template-parameter of a primary class template or alias template is a template parameter pack, it shall be the last template-parameter.[...]

    (if they were deduced it would be ambiguous as in the function template example).

    0 讨论(0)
提交回复
热议问题