默认参数模板与可变参数模板:最后一个模板参数是什么?

Vin*_*ent 12 c++ templates variadic-templates c++11

我有点困惑,因为默认参数模板和可变参数模板参数都必须是模板的最后一个参数.那么我的函数的官方语法是什么?

template<typename T, class T2 = double, unsigned int... TDIM> myFunction(/* SOMETHING */)
Run Code Online (Sandbox Code Playgroud)

要么

template<typename T, unsigned int... TDIM, class T2 = double> myFunction(/* SOMETHING */)
Run Code Online (Sandbox Code Playgroud)

Xeo*_*Xeo 18

其实,模板参数包和默认参数不具备成为最后一个功能,如果任何东西来以后,会推导出(或默认的):

template<class T, class... Args, class T2 = int, class T3>
void f(T3){}
Run Code Online (Sandbox Code Playgroud)

请注意,您永远不能指定任何内容T2,因为variadic包会吞下所有内容.总结一下,我认为将variadic包放在默认参数之后是有意义的,如果要手动指定它们的话.对于演绎包,它更像是一种风格选择,我个人会把它们放在最后.

请注意,如果它们被推断为另一个模板的一部分,您甚至可以拥有多个可变参数包:

template<class...> struct pack{};

template<class T, class... P1, class... P2, class T2>
void f(pack<P1...>, pack<P2...>, T2){}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我将包和其他模板参数相对于它们的函数参数,即以相同的顺序.

对于(主)类模板,当然这是不同的,因为不存在推导出的参数.实际上,可变参数包必须位于模板参数列表的末尾:

template<class T, class... Args, class T2=int>
struct X{}; // error
Run Code Online (Sandbox Code Playgroud)

对于部分专业化,订单无关紧要,这又是一种纯粹的风格选择.我个人会把它们放在主要模板的参数上,就像之前一样.

template<class T1, class T2>
struct X{};

template<template<class...> class T1, class... A1,
    template<class...> class T2, class... A2>
struct X<T1<A1...>, T2<A2...>>{};
Run Code Online (Sandbox Code Playgroud)