N4527 14.5.5.1 [temp.class.spec.match]
2如果可以从实际模板参数列表推导出部分特化的模板参数,则部分特化匹配给定的实际模板参数列表。
template<class T1, class T2, int I> class A { }; // #1 template<class T, int I> class A<T, T*, I> { }; // #2 template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3 template<class T> class A<int, T*, 5> { }; // #4 template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5 A<int, int, 1> a1; // uses #1 A<int, int*, 1> a2; // uses #2, T is int, I is 1 A<int, char*, 5> a3; // uses #4, T is char A<int, char*, 1> a4; // uses #5, T1 is int, T2 is char, I is 1 A<int*, int*, 2> a5; // ambiguous: matches #3 and #5
3还可以从主模板的非类型参数的实际模板参数的值推导出非类型模板参数。 [例如:上面
a2
的声明。 - 例子]4在引用类模板特化的类型名称中(例如
A<int, int, 1>
)参数列表应 匹配主模板的模板参数列表。专业化的模板参数是 从主要模板的参数推断出来。
在rule3中,示例显示I
是从第三个实际模板参数1
中推导出来的,这就是rule2所说的内容。因此,作为规则4的第二句,我认为重复规则2所说的。
它们之间有什么区别(规则2,规则3和规则4)?
换句话说,我们已经有了rule2,rule3的意图(含义)和rule4的第二句是什么,为什么他们在这里?
答案 0 :(得分:2)
规则2和规则4之间的差异是第二个和第三个模板参数。在示例三中:
A<int, char*, 5> a3; // uses #4, T is char
它使用rule4,因为第三个参数明确专门用于const int 5,第二个参数专门用于接受指针类型;它是class A
的独特专长。
我将每个专业化视为该类的特定种类,并且每个种类都具有唯一的签名(类似于重载函数)。编译器将选择与正在使用的签名匹配的特化。
规则三只有在没有规则五的情况下才有意义,因此在删除规则五之后,规则三的目的是专门化class A
的任何类型名称:
a) do not use a const int 5 for the third parameter
b) do not use a pointer or as the second parameter
c) do not use a `int` in the second parameter.
:
template<...>
由于您的示例中没有使用rule3的唯一签名,因此不使用rule3(假设我们删除了不明确的规则5)。
如果您只查看专业化的<>
方案,而不是专业化的签名class A
,则可以更好地理解。在查看专门化之前,编译器正在查看模板方案。此外,{{1}}的所有其他专业化定义了任何新专业化的规则。要理解专业化的意图,你必须理解所有其他专业的意图,并且专业化的意图不是由标准定义的,它由实施专业化的人定义;即。专业化的实施细节真正定义了意图。
答案 1 :(得分:2)
我认为,规则 [temp.class.spec.match] 14.5.5.1 \ 2 可以像这样重写而不改变其主旨:
[temp.class.spec.match] 14.5.5.1 \ 2(已修改)
部分特化匹配给定的实际模板参数列表 如果可以推导出部分特化的模板参数 根据14.8.2.5的实际模板参数列表,其中P 是来自它的部分特化的参数列表 simple-template-id ,A是实际的模板参数列表。
规则 [temp.deduct.type] 14.8.2.5 \ 1 仅定义了从类型推导的过程(我不确定模板),因此需要规则 [temp.class.spec.match] 14.5.5.1 \ 3 ,使用主要模板的非类型模板参数添加到 14.5.5.1 \ 2 个案,其中不是(部分)专门从事部分专业化。
您在上面的评论(1,2)中提到的规则 [temp.class.spec.match] 14.5.5.1 \ 4 只是澄清一下, template-id 中的模板参数对应于主模板的模板参数,而不是其部分特化,它们可能具有不同的 template-parameter-list 。此外,规则的第二句很可能声称主要模板的隐式模板参数列表( 14.5.5 \ 4 )是根据 [temp.deduct。]推导出来的(!)。从实际参数列表中输入] 14.8.2.5 \ 9 。所以短语&#34;隐含模板参数列表的主要模板&#34;和&#34;专业化的模板参数&#34;意味着一个同样的东西,以及短语&#34;主要模板的参数&#34;和&#34;实际的模板参数列表&#34;意味着另一个同样的事情......但也可能是作者打算写这个:
[temp.class.spec.match] 14.5.5.1 \ 4(已修改)
在引用类模板特化的类型名称中,参数列表应与主模板的模板参数列表匹配。部分特化的模板参数是从主模板的参数推导出来的。
...无论