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

12

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

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

或者

template<typename T, unsigned int... TDIM, class T2 = double> myFunction(/* SOMETHING */)
1个回答

18
实际上,模板参数包和默认参数不一定要在函数的最后,如果在它之后的任何内容都可以被推断出(或者是默认的):
template<class T, class... Args, class T2 = int, class T3>
void f(T3){}

请注意,由于可变参包会吞噬一切输入,因此您无法为 T2 指定任何内容。因此,如果要手动指定可变参包,则最好将其放在默认参数后面。对于推断出的可变参包,这更多是样式选择,我个人会将它们放在最后。
请注意,如果它们作为另一个模板的一部分被推断出来,甚至可以有多个可变参包:
template<class...> struct pack{};

template<class T, class... P1, class... P2, class T2>
void f(pack<P1...>, pack<P2...>, T2){}

在这种情况下,我会根据它们的函数参数将包和其他模板参数放置在同一位置,即按顺序排列。
对于(主要的)类模板,当然是不同的,因为无法推断出参数。实际上,可变参数包必须位于模板参数列表的末尾:
template<class T, class... Args, class T2=int>
struct X{}; // error

对于部分特化,顺序并不重要,这只是一个纯粹的风格选择。我个人会将它们相对于主模板的参数放置,例如在其之前。

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...>>{};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接