[英]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;
}
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
So T
is actually deduced as a pointer to a constant integer. 因此,
T
实际上被推导为指向常数整数的指针。 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. 参数是const的引用这一事实不会改变推论,这是人们所期望的,因为指针的常量是低级的。
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
So T
is actually deduced as an array of 3 non -const integers. 因此,
T
实际上被推导为3个非对齐整数的数组。 The fact that the argument is a reference-to-const does change the deduction, as if the const
was slipping into the array elements. 参数是const的引用这一事实确实改变了推论,就好像
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 (ie, deducing as non -const). 实际上,最多18个CL的版本推导
T
作为3个const整数的数组是我期望的标准,但似乎从v19它收敛到GCC和Clang正在做的事情(即推导为非 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.
它看起来不像指针一样令人惊讶。
Edit: 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问题,指针他居然张贴在评论这个答案 (答案,实际上提出了这个新的问题?C ++感觉就像一个深隧道)
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)
^^^^^^^^^^ ^^^^^^^^^^
Note: This is pseudocode. 注意:这是伪代码。 The full type is
const int* const&
. 完整类型是
const int* const&
。
Note that the const int
remains const int
, but the *
becomes * const
. 请注意,
const int
仍然是const int
,但*
变为* const
。
This is because const int*
is just a regular, mutable, non-volatile pointer. 这是因为
const int*
只是一个常规的,可变的,非易失性的指针。 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)
^^^^^^ ^^^^^^
Note: This is pseudocode. 注意:这是伪代码。 The real type would be
const int (&a)[3]
. 真实的类型是
const int (&a)[3]
。
So the type deduction is working the same in both cases, discarding the outer const
. 因此类型推导在两种情况下都是相同的,丢弃外部
const
。
It so happens that a const
array is the same as an array of const
elements. 碰巧
const
数组与const
元素数组相同。
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. 在第二个例子中,
const
似乎“移动”从应用于数组到应用于元素。 This is because you can't really have a const
array, only an array of const
elements. 这是因为你没有真正有一个
const
数组,只有数组const
元素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.