[英]Why does template parameter deduction for T 'skips' the constness of array elements when function parameter is const reference to T?
让我们考虑一下这些定义:
/*** 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 int i=5, *ip=&i;
func(ip);
输出是:
Deduced type for T is: 4TypeI**PKi**E
因此, T
实际上被推导为指向常数整数的指针。 参数是const的引用这一事实不会改变推论,这是人们所期望的,因为指针的常量是低级的。
但是,如果执行以下语句:
const int ia[3] = {3, 2, 1};
func(ia);
输出是:
Deduced type for T is: 4TypeI**A3_i**E
因此, T
实际上被推导为3个非对齐整数的数组。 参数是const的引用这一事实确实改变了推论,就好像const
正在滑入数组元素一样。
实际上,最多18个CL的版本推导T
作为3个const整数的数组是我期望的标准,但似乎从v19它收敛到GCC和Clang正在做的事情(即推导为非 const)。
因此,我认为后来的行为是标准的,但是理由是什么? 它看起来不像指针一样令人惊讶。
编辑:继浸评论,我会在这里的指针报告与此相关的行为CWG问题,指针他居然张贴在评论这个答案 (答案,实际上提出了这个新的问题?C ++感觉就像一个深隧道)
使用此函数模板原型:
template <typename T> void func(const T& a);
在第一个示例中,类型推导的工作原理如下:
const int* ip;
func(ip) => func<const int*>(const (const int*)& a)
^^^^^^^^^^ ^^^^^^^^^^
注意:这是伪代码。 完整类型是const int* const&
。
请注意, const int
仍然是const int
,但*
变为* const
。
这是因为const int*
只是一个常规的,可变的,非易失性的指针。 这只是一个*
。 它所指的是无关紧要的。
但在第二个例子中,你有:
const int ia[3];
func(ia) => func<int[3]>(const (int[3])& a)
^^^^^^ ^^^^^^
注意:这是伪代码。 真实的类型是const int (&a)[3]
。
因此类型推导在两种情况下都是相同的,丢弃外部const
。
碰巧const
数组与const
元素数组相同。
写这样的类型可能会有所帮助:
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])
在第二个例子中, const
似乎“移动”从应用于数组到应用于元素。 这是因为你没有真正有一个const
数组,只有数组const
元素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.