为什么模板参数扣T'跳跃'数组元素的常量性时,函数参数是const引用到T? [英] Why does template parameter deduction for T 'skips' the constness of array elements when function parameter is const reference to T?
问题描述
让我们考虑一下这些定义:
Let's consider those definitions:
/*** full type information with typeid ***/
template <class> class Type{};
template <class T> std::string typeStr()
{ return typeid(Type<T>).name(); }
/*** function template for parameter deduction ***/
template <class T> void func(const T &a)
{
std::cout << "Deduced type for T is: " << typeStr<T>() << std::endl;
std::cout << "\targument type is: " << typeStr<decltype(a)>() << std::endl;
}
的指针为const
如果下面的语句执行:
with pointers to const
If the following statements are executed:
const int i=5, *ip=&i;
func(ip);
输出是:
The output is:
Deduced type for T is: 4TypeI**PKi**E
所以 T
实际上推导出一个指向一个常数整数。事实上,参数是一个引用给const不会改变扣,这是人们所期望的,因为指针的常量性是低层次的。
So T
is actually deduced as a pointer to a constant integer. The fact that the argument is a reference-to-const does not change the deduction, which is what one would expect because the constness of the pointer is low-level.
不过,如果下面的语句执行:
Nonetheless, if following statements are executed:
const int ia[3] = {3, 2, 1};
func(ia);
输出是:
The output is:
Deduced type for T is: 4TypeI**A3_i**E
所以 T
实际上推导出的3 非 -const整数数组。事实上,参数是一个引用给const 并更改扣,仿佛常量
滑倒到数组元素。
So T
is actually deduced as an array of 3 non-const integers. The fact that the argument is a reference-to-const does change the deduction, as if the const
was slipping into the array elements.
其实,CL版本多达18人演绎 T
为3常量整数数组是我预计的标准,但似乎因为V19它融合到什么GCC和锵正在做的(也就是说,演绎为非 -const)。
Actually, versions of CL up to 18 were deducing T
as array of 3 const integers was what I expected to be standard, but it seems that since v19 it converged to what GCC and Clang are doing (i.e., deducing as non-const).
因此,我认为以后的行为是标准的,但是是什么道理呢?这可能似乎令人惊讶的是它并不像表现的指针。
Thus, I assume the later behaviour to be standard, but was is the rationale ? It could seem surprising that it does not behave like with pointers.
编辑:以下的浸的评论,我会在这里报告指针到与此相关的行为CWG的问题,他居然张贴上的这个答案(答案其实提出这个新的问题... C ++感觉就像一个深隧道)
Following dip comment, I will report here pointers to CWG issues related to this behaviour, pointers he actually posted as a comment on this answer (answer that actually raised this new question... C++ feels like a deep tunnel)
- CWG 1059
- CWG 1610
- CWG 112
推荐答案
使用这个函数模板的原型:
Using this function template prototype:
template <typename T> void func(const T& a);
在你的第一个例子中,类型推演工作方式:
In your first example, the type deduction works as:
const int* ip;
func(ip) => func<const int*>(const (const int*)& a)
^^^^^^^^^^ ^^^^^^^^^^
注:这是伪code。完整的类型是 const int的* const的&放大器;
请注意, const int的
遗体 const int的
,而 *
变成 * const的
。
Note that the const int
remains const int
, but the *
becomes * const
.
这是因为 const int的*
只是一个普通的,可变的,非易失性的指针。这仅仅是一个 *
。它所指向的是无关紧要的。
This is because const int*
is just a regular, mutable, non-volatile pointer. It is just a *
. What it points to is irrelevant.
但是,在第二个例子中,有:
But in the second example, you have:
const int ia[3];
func(ia) => func<int[3]>(const (int[3])& a)
^^^^^^ ^^^^^^
注:这是伪code。真正的类型将是 const int的。(安培;一)[3]
所以类型推演工作同样在这两种情况下,丢弃外侧常量
。
So the type deduction is working the same in both cases, discarding the outer const
.
事实上,有一个常量
数组是一样的常量
元素的数组。
It so happens that a const
array is the same as an array of const
elements.
这可能有助于写类型是这样的:
It might help to write types like this:
template <typename T> func(T const & a);
int const * ip;
func(ip) => func<int const *>(int const * const & a)
int const ia [3];
func(ia) => func<int [3]>(int const (& a) [3])
在这第二个例子中,常量
似乎从阵列上被应用到的元素被应用移动。这是因为你没有真正有一个常量
阵中,只有常量
元素的数组。
On that second example, the const
appears to "move" from being applied on the array to being applied on the elements. This is because you can't really have a const
array, only an array of const
elements.
这篇关于为什么模板参数扣T'跳跃'数组元素的常量性时,函数参数是const引用到T?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!