模板参数替换的惊喜?

时间:2017-05-15 13:12:26

标签: c++ templates c++14 language-lawyer

N3690,§14.8.2第3段有一个非常令人兴奋的例子:

template <class Z> void h(Z, Z*);
// #5: function type is h(int, const int*)
h<const int>(1,0);

问题:为什么不是h(const int, const int*)

据了解,Z = const int,模板声明中Z的每次出现都可以理解为const int,或者我遗漏了什么?为什么指针不同?我记得当参数有T&T*时,它会保留T的cv限定符,但我认为没有可能在此处应用它。

3 个答案:

答案 0 :(得分:11)

您需要查看[dcl.fct] / 5,原因如下:

  

单个名称可用于单个范围内的多个不同功能;这是函数重载(第13条)。函数的所有声明都应在return类型和parameter-type-list中完全一致。使用以下规则确定函数的类型。每个参数的类型(包括函数参数包)由其自己的decl-specifier-seq和声明符确定。在确定每个参数的类型之后,将“T数组”或“函数返回T”类型的任何参数分别调整为“指向T的指针”或“指向函数返回T的指针”。 生成参数类型列表后,在形成函数类型时,将删除修改参数类型的任何顶级cv限定符。生成的已转换参数类型列表以及省略号或函数参数包的存在与否是函数的parameter-type-list。 [注意:此转换不会影响参数的类型。例如,int()(const int p,decltype(p))和int()(int,const int )是相同的类型。 - 后注]

const type* the const is not a top level const qualifier

答案 1 :(得分:10)

原因是另一个标准段落:

[dcl.fct/5]

  

单个名称可用于单个中的多个不同功能   范围;这是函数重载。函数的所有声明   应完全同意退货类型和   参数类型列表。使用函数确定函数的类型   遵守规则。每个参数的类型(包括功能   参数包)是由它自己的decl-specifier-seq和   声明符。在确定每个参数的类型后,任何   “T的数组”或函数类型T的参数被调整为   “指向T的指针”。生成参数类型列表后, any   修改参数类型的顶级cv限定符将在删除时删除   形成函数类型。生成的转换列表   参数类型和省略号的存在或不存在   function parameter pack是函数的参数类型列表。 [ 注意:   此转换不会影响参数的类型。对于   例如,int()(const int p,decltype(p))和int()(int,const int )   是相同的类型。 - 结束说明]

对此的合理化是,对于调用者,如果参数是cv-qualified,则没有区别;调用函数的步骤以及重载决策的转换序列是相同的。因此,保留const实际上可能导致含糊不清。

cv-qualifier实际上是函数的实现细节,仅在函数定义的位置有意义(你不能修改函数体内的参数)。

答案 2 :(得分:2)

因为一般来说,您需要从基本的非POD类型remove cv-qualifiers

来自§ 8.3.5 Functions的{​​{3}}(第181页):

  

5

     

单个名称可用于a中的多个不同功能   单一范围;这是函数重载(第13条)。所有   函数的声明应在回报中完全一致   类型和参数类型列表。确定函数的类型   使用以下规则。每个参数的类型(包括   函数参数包)是由它自己决定的   decl-specifier-seq和声明符。确定每个的类型后   参数,“数组T”或“函数返回”类型的任何参数   T“被调整为”指向T的指针“或”指向函数返回的指针   T,“分别。生成参数类型列表后,任何   修改参数类型的顶级cv限定符将在删除时删除   形成功能类型。生成的转换参数列表   类型和省略号或函数的存在或不存在   参数包是函数的参数类型列表。 [注意:这个   转换不会影响参数的类型。对于   例如,int()(const int p,decltype(p))和int()(int,const int )   是相同的类型。 - 后注]

C++11个基本的非POD类型。