模板参数包如何具有其他尾随参数?

How can a template parameter pack have other trailing arguments?

本文关键字:参数 其他 包如何      更新时间:2023-10-16

在C++14标准草案中,[temp.param]/11说:

如果是主类模板或别名模板的模板参数 是一个模板参数包,它应该是最后一个模板参数。

如果您尝试编译以下模板,则编译器将抱怨。

template< typename ...Args, void(*f)(Args...) > // ERROR
struct Bar
{};

但是在这种情况下它是如何工作的呢?

template< typename F, F >
struct Bar;
template< typename ...Args, void(*f)(Args...) > // OK ???
struct Bar< void(*)(Args...), f >
{};

我可以看到它与它是专业化类模板的一部分有关,但为什么呢?

该规则明确指出它适用于类模板。这是否意味着专业化的规则会发生变化?

我试图在标准中搜索这个,但找不到任何东西。你能不能对此有所了解。

该规则明确指出它适用于主类模板。这是否意味着专业化的规则会发生变化?

是的。很简单,因为专业化不是主要类模板。因此,如果措辞旨在适用于所有模板声明,它将这样说。相反,该规则非常适用于主类模板(...和别名模板,不能专门化(。专业化没有这样的限制。

从根本上说,这是因为不可能在主模板中的模板参数包之后提供任何模板参数,但在专用化中绝对可以这样做。例如,以下是连接两个tuple专业化的一种方法:

template <typename T, typename U>
struct tuple_concat;
template <typename... Ts, typename... Us> // <== parameter pack *after* parameter pack
struct tuple_concat<tuple<Ts...>, tuple<Us...>> {
using type = tuple<Ts..., Us...>;
};

这很好,它有效,很有用。但是能够在主类/变量/别名模板中编写这样的东西没有任何好处 - 因此禁止简单。


与C++的所有事情一样,当然有一个脚注。您本可以提供用于触发替换失败的尾随默认模板参数。但是还有其他方法可以解决这个问题,然后我们很快就会有概念画板。