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

问题描述 投票:3回答:1

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

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

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

我试图在标准中搜索这个,但找不到任何东西。你能不能为此发光一点。

c++ templates c++14 variadic
1个回答
3
投票

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

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

这基本上是因为在主模板中的模板参数包之后不可能提供任何模板参数,但在专业化中肯定可以这样做。例如,这是连接两个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 ++一样,当然有一个脚注。您本可以提供用于触发替换失败的尾随默认模板参数。但是还有其他方法可以解决这个问题,然后我们很快就会有概念。

© www.soinside.com 2019 - 2024. All rights reserved.