当部分专用化参数不使用其任何模板参数时,哪些规则适用

Which rules apply when an argument of partial specialization does not use any of its template parameters

本文关键字:参数 规则 专用 当部 任何模      更新时间:2023-10-16

N4567 [临时.class.规格匹配]P2

如果可以从实际模板参数列表 (14.8.2( 推导出部分专用化的模板参数,则部分专用化与给定的实际模板参数列表匹配。

template<class T, class U>
struct S{};
template<class U>
struct S<int, U>{};
S<char, int> s;

我知道部分专用化S<int, U>与实际的模板参数列表不匹配char, int,第二个参数U可以从 14.8.2.5 int

推断出来。

但我不知道 14.8.2 中的哪些规则适用于第一个参数int.

14.8.2.5 [温度扣除类型]p1

模板参数可以在几个不同的上下文中推导,但在每种情况下,根据模板参数指定的类型(称为 P (与实际类型(调用它 A (进行比较,并尝试查找模板参数值(类型参数的类型、非类型参数的值、 或模板参数的模板(,在替换推导的值后,将产生P(称为 推导A(,兼容A

据我了解,S<int, U> 中的int没有根据模板参数指定,因此 14.8.2.5 适用。

想知道哪些规则处理这种情况,或者您可以纠正我关于 14.8.2.5


换句话说:直观地说,部分专业化S<int, U>不匹配char,int因为char不匹配int

我想知道哪些规则确定charint不匹配。

在我的理解中,S 中的 int 不是根据模板参数指定的,因此 14.8.2.5 不适用。

不,14.8.2.5解释了如何推断类型,14.3处理模板参数,您发布的代码失败14.3p1

14.3p1 ...模板 id 中指定的每个模板参数的类型和形式应与模板在其模板参数列表中声明的相应参数指定的类型和形式匹配。

template<class T, class U>
struct S<int, U> {}; 
// compiler error, template parameters not used in partial specialization

应该是

template<class U>
struct S<int, U> {};

所以

#1
template<class T, class U>
struct S{};
#2
template<class U>
struct S<int, U> {};
S<char, int> s; // uses #1
S<int, char> c; // uses #2 since S<int, U> matches more closely than S<T, U>

你提到gcc拒绝了模板,而clang接受了它。在我的测试中,VC++gcc 默认给出一个编译器错误,并且根本没有编译代码,但是,clang给出了一个警告,而是指出this partial specialization will never be used并构建了二进制文件。因此,在所有情况下,它都会发出不符合项的通知,这只是默认情况下打开的编译器设置以及编译器实现如何处理不符合代码的问题。

希望能有所帮助。

在考虑这里发生的事情时:

template<class T, class U> struct S{}; // (1)
template<class U> struct S<int, U>{};  // (2)
S<char, int> s; // (1) or (2)?

为了确定我们用于s的专业化,我们进入[temp.class.spec.match]:

当类模板在需要类实例化的上下文中使用时,有必要 确定是使用主模板还是使用部分模板之一生成实例化 专门化。这是通过将类模板专用化的模板参数与 模板参数列出了部分专用化。

在本例中,我们将<char, int><int, U>进行匹配。匹配是什么意思?

部分专用化与给定的实际模板参数列表匹配,如果 可以从实际模板参数列表 (14.8.2( 中推断出部分专用化。

基本上,我们正在推断U以匹配int == charU == int。等价地,我们正在考虑推断U

template <class U> void f(S<int, U> );
f(S<char, int>{} );

没有这样的扣除。

这导致我们:

— 如果未找到匹配项,则从主模板生成实例化。

这导致我们(1) .

让我们举一个更有趣的案例:

S<int, char> s2;

现在,<int, char>对阵<int, U>的比赛,因为我们可以推断出U=char。因此:

— 如果只找到一个匹配的专用化,则从该专用化生成实例化。

这导致我们(2) .