【问题标题】:What does "The template arguments of a specialization are deduced from the arguments of the primary template" mean?“专业化的模板参数是从主模板的参数推导出来的”是什么意思?
【发布时间】:2015-12-31 22:19:49
【问题描述】:

N4567 14.5.5.1 [temp.class.spec.match]p4

在引用类模板特化的类型名称中,(例如,A)参数列表应 匹配主模板的模板参数列表。 特化的模板参数是从主模板的参数推导出来的。

template<class T1, class T2, int I> class A             { }; // #1
template<class T, int I>            class A<T, T*, I>   { }; // #2
A<int, int, 1>   a1; // uses #1

这个“推断”是指 14.8.2.5 [temp.deduct.type] 吗?

可以在几种不同的上下文中推导出模板参数,但在每种情况下,都会将根据模板参数指定的类型(称为P)与实际类型(称为A)进行比较,然后在替换推导的值(称为推导出A),与A兼容。

如果有,P和A是什么?

特化的模板参数表示主模板实际模板参数int, int, 1部分专业化 T, T*, I 或其他的模板参数?

主模板的参数表示主模板的实际模板参数int, int, 1 主模板的隐式模板参数 T1, T2, I 或其他?

这句话是什么意思?


更新:

看起来@Igor Tandetnik 和@R Sahu 有不同的答案,我需要更多帮助。

【问题讨论】:

  • A 将是 intint1P 将是 TT*I(像往常一样,每个参数的推导都是单独执行的)。在这种情况下,第二个参数的推导失败(T* 中的 T 不能从 int 推导),因此实例化了主模板,而不是特化。
  • @IgorTandetnik 所以这句话只是重复 14.5.5.1/2 如果部分特化的模板参数可以从实际模板参数推导出来,则部分特化匹配给定的实际模板参数列表列表?
  • 不完全重复。 p2 说“可以推断”,所以它只问一个答案是“真”或“假”的问题。 p4 表示“推断”,因此它设想了一个实际为这些参数分配值的过程。但是,是的,它们密切相关。
  • @stackcpp 关于 R Sahu 的回答,我在那里写了评论。关于你的问题“专业化的模板参数”这个短语意味着什么以及“主模板的参数”这个短语是什么意思,我的回答是here

标签: c++ templates language-lawyer


【解决方案1】:

首先,应该注意these rules 的含义更像是您正在实现 C++ 解析器(如编译器),因此如果不满足这些特定规则之一,则该程序应该是不合格的(并产生错误)。所以在你提到的段落中:

在引用类模板特化的类型名称中(例如,A&lt;int, int, 1&gt;),实参列表应与主模板的模板形参列表匹配。特化的模板参数是从主模板的参数推导出来的。

可以认为,如果被解析的源不符合这些段落的限制,那么它就是不符合的,所以会产生错误。

直接回答主要问题:

“专业化的模板参数是从主模板的参数推导出来的”是什么意思?

14.5.5 是关于模板的部分特化,14.5.5.1 是专门关于匹配部分特化,第 4 段(句子的来源)只是说传递给模板的模板参数必须匹配专门模板的参数.

第 4 段的最后一句话(有问题的那个),只是说传入的参数是基于主模板推导出来的。

在谈到这一段时,它给出了一个A&lt;int, int, 1&gt; 的例子,它指的是它在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是什么?

这句话中的PA 只是用于其余文本的占位符值。

具体来说,P 表示模板参数,A 表示可以使用的实际类型,例如 intstd::string 或用户定义的类型比如classstructtypedef,或函数。

以这段代码为例:

#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 用于 a1double 用于 a2someVal 用于 @ 987654368@。因为that will make P, after substitution of the deduced values (call it the deduced A), compatible with A 不存在类型someVal 不是有效类型,所以符合标准的编译器应该为a3 生成错误。

使用上面的示例A&lt;int, int, 2.0f&gt; a3;,因为没有定义可以采用最后一个参数(2.0f)的模板,所以这里的P val 是intA val 是@987654377 @;由于2.0f不是int,所以这个模板推演失败并产生错误。

你还问过:

特化的模板参数是指主模板 int、int、1 的实际模板参数,还是部分特化 T、T*、I 或其他的模板参数?

The template arguments of a specialization 是指传递给模板的参数,所以在A&lt;int, int, 1&gt; 中,这个特化的模板参数是intint1

主模板的参数是指主模板的实际模板参数 int、int、1 还是主模板 T1、T2、I 或其他的隐式模板参数?

the arguments of the primary template 指的是主模板本身,因此在上面的A 示例中,主模板将是template&lt;class T1, class T2, int I&gt; class A { };

希望能帮到你。

【讨论】:

  • 你的意思是int, int, 1是从T1, T2, I推导出来的?
  • @stackcpp,反过来说,T1, T2, I是从int, int, 1推导出来的
  • 在你的回答中你说“专业化的模板参数是......”和“主模板的参数是指......”,用它们替换14.5.5.1p4中的单词然后我得到“int, int, 1是从T1, T2, I推导出来的”
【解决方案2】:

鉴于您的模板及其专业化,使用:

A<int, int*, 1>   a2;

将使用专业化。

对于这种用法,

主模板的模板参数为intint*1
模板特化的模板参数是int1

特化的参数int1 是从主模板的参数intint*1 推导出来的。

在这种情况下,

Pintint*1
A 是专业化。

我认为这就是您正在寻找的答案。

【讨论】:

  • @stackcpp、Pintint*1
  • @stackcpp,将根据模板参数指定的类型(称为 P)与实际类型(称为 A)进行比较。我对此的解释是 Pint, int*, and 1. Those are the template parameter used to create the object a2. A` 实际类型,即模板特化。
  • @stackcpp,我不明白结果是什么的意思。你在说什么结果
  • @stackcpp,推演结果是模板特化,模板参数int1,用于构造a2
  • @R Sahu 您能否使用问题中的选项告诉我“专业化的模板参数意味着”和“主模板的参数意味着”。并将其写入您的答案中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-10
  • 1970-01-01
  • 2017-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多