首先,应该注意these rules 的含义更像是您正在实现 C++ 解析器(如编译器),因此如果不满足这些特定规则之一,则该程序应该是不合格的(并产生错误)。所以在你提到的段落中:
在引用类模板特化的类型名称中(例如,A<int, int, 1>),实参列表应与主模板的模板形参列表匹配。特化的模板参数是从主模板的参数推导出来的。
可以认为,如果被解析的源不符合这些段落的限制,那么它就是不符合的,所以会产生错误。
直接回答主要问题:
“专业化的模板参数是从主模板的参数推导出来的”是什么意思?
14.5.5 是关于模板的部分特化,14.5.5.1 是专门关于匹配部分特化,第 4 段(句子的来源)只是说传递给模板的模板参数必须匹配专门模板的参数.
第 4 段的最后一句话(有问题的那个),只是说传入的参数是基于主模板推导出来的。
在谈到这一段时,它给出了一个A<int, int, 1> 的例子,它指的是它在14.5.5.1 给出的例子中的其他模板特化(为了便于阅读而分开):
// #1 (main template)
template<class T1, class T2, int I>
class A
{ };
// #2
template<class T, int I>
class A<T, T*, I>
{ };
// #3
template<class T1, class T2, int I>
class A<T1*, T2, I>
{ };
// #4
template<class T>
class A<int, T*, 5>
{ };
// #5
template<class T1, class T2, int I>
class A<T1, T2*, I>
{ };
所以,给定以下代码:
A<int, int, 1> a1;
A<int, char*, 5> a2;
A<int, int, 2.0f> a3;
A<int*> a4;
a1 可以正常编译,并且模板#1 将被使用(因为它与该专业化完全匹配),因此模板#1 将编译为以下内容:
template<
class T1 = int,
class T2 = int,
int I = 1>
class A
{ };
a2 也可以正常编译,模板#4 将被这样使用:
template<
class T = char>
class A<int, T*, 5>
{ };
但是,a3 与任何模板特化都不匹配,并且在编译 a3 时,符合要求的编译器会产生错误,因为 int 的类型与 float 的类型不匹配;也就是说,a3 将生成以下类型的模板:
template<
class T1 = int,
class T2 = int,
int I = 2.0f>
class A
{ };
因此应该会产生一个错误,因为int 不是float。最后,a4 也不会编译,因为它只有 1 个模板参数,而 A 的所有模板特化都需要 3 个参数。
继续你的问题:
这个“推断”是指 14.8.2.5 [temp.deduct.type] 吗?
是与否,deduced 指的是整个14.8.2 Template argument deduction,其中第 2 段指出:
当指定显式模板实参列表时,模板实参必须与模板形参列表兼容,并且必须产生如下所述的有效函数类型;否则类型推导失败。
为了简洁起见,described below 的其他要点未在此处发布。
然而,14.8.2.5 专门指 如何 以符合的方式推断类型,如果不能以这种方式推断模板特化,那么它应该会失败(即编译器应该生成错误)。
如果有,P和A是什么?
这句话中的P 和A 只是用于其余文本的占位符值。
具体来说,P 表示模板参数,A 表示可以使用的实际类型,例如 int 或 std::string 或用户定义的类型比如class、struct 或typedef,或函数。
以这段代码为例:
#1
template < class T >
struct A {
T val;
};
#2
template<>
struct A<double>
{
double val;
};
int main() {
A<int> a1; // uses #1
A<double> a2; // uses #2
A<someVal> a3; // uses #1 but generate error since `someVal` is invalid type
}
在此代码中,P val 将是 class T 的模板参数,A val 将是 int 用于 a1,double 用于 a2 和 someVal 用于 @ 987654368@。因为that will make P, after substitution of the deduced values (call it the deduced A), compatible with A 不存在类型someVal 不是有效类型,所以符合标准的编译器应该为a3 生成错误。
使用上面的示例A<int, int, 2.0f> a3;,因为没有定义可以采用最后一个参数(2.0f)的模板,所以这里的P val 是int,A val 是@987654377 @;由于2.0f不是int,所以这个模板推演失败并产生错误。
你还问过:
特化的模板参数是指主模板 int、int、1 的实际模板参数,还是部分特化 T、T*、I 或其他的模板参数?
The template arguments of a specialization 是指传递给模板的参数,所以在A<int, int, 1> 中,这个特化的模板参数是int、int 和1。
主模板的参数是指主模板的实际模板参数 int、int、1 还是主模板 T1、T2、I 或其他的隐式模板参数?
the arguments of the primary template 指的是主模板本身,因此在上面的A 示例中,主模板将是template<class T1, class T2, int I> class A { };
希望能帮到你。